3. Distribution of Individual Features
To prepare the dataset for our analysis purpose, we utilized the sample
function to create some missingness in our dataset. We randomly replaced
5% of all feature variables with missing values to make the dataset
represent real world data which is often observed with missing values in
variables. It is important to point out that since this is an already
cleaned dataset, there are not much to be done in addressing issues like
unlikely values ( extreme height or weight, etc, non standard response
to questionnaires among others). We will utilize exploratory data
analysis to uncover patterns and relationships in the dataset. Feature
engineering will be applied where applicable to create new variables and
a visual representation of the data will be provided to identify trends
and feature variable distributions. Additionally, sub group
visualizations will be presented that enlightens our understanding of
how diabetes affects certain groups of people and which feature
variables are associated with diabetes.
- Individual analytic tasks - The following feature
variables comprise of some of the risk factors that are reported to be
associated with diabetes that will be studied.
- BMI: BMI histogram showed positively skewed data while a box plot
also showed outliers. The outliers were removed from the dataset that
were 1.5 times lower or higher than the first and third quartiles. The
plot of the data without the outliers showed a smoother distribution.
BMI was re-categorized into Underweight, Normal, Overweight and Obese.
Over 70% of the sample were either overweight or obese to help identify
at risk populations and easier interpretation of the data and for trend
identification. It was apparent that most of the participants where
either over weight or obese.
# get data into R
#setwd("~")
#getwd()
library(dplyr)
#ddat <- read.csv("/Users/mkatuahene/Desktop/WCU/R-Machine Learning/Assignment/Week 2/diabetes_binary_health_indicators_BRFSS2015.csv", skip=0)
ddat <- read.csv("https://matuahene.github.io/STA552/Week%202/diabetes_binary_health_indicators_BRFSS2015.csv", skip=0)
#getwd()
# Categorize income variable
ddat$Income_cat <- cut(ddat$Income,
breaks = c(-Inf, 3, 5, 6, Inf),
labels = c("Low", "Medium", "High", "Very High"))
#table(ddat$Income , ddat$Income_cat )
ddat2 <-ddat
#colSums(is.na(ddat2))
# assign meaningful labels to Age
ddat2$Age <- factor(ddat2$Age,
levels = 1:13,
labels = c("18-24 yrs", "25-29 yrs", "30-34 yrs", "35-39 yrs", "40-44 yrs",
"45-49 yrs", "50-54 yrs", "55-59 yrs", "60-64 yrs", "65-69 yrs",
"70-74 yrs", "75-79 yrs", "80+ yrs"))
# BMI categories
ddat2 <- ddat2 %>%
mutate(BMI_Cat = cut(BMI,
breaks = c(0, 18.5, 24.9, 29.9, Inf),
labels = c("Underweight", "Normal", "Overweight", "Obese")))
# YES/NO labels
ddat2 <- ddat2 %>%
mutate(
HighChol = recode(HighChol, "0" = "No", "1" = "Yes"),
HighBP = recode(HighBP, "0" = "No", "1" = "Yes"),
Smoker = recode(Smoker, "0" = "No", "1" = "Yes"),
Stroke = recode(Stroke, "0" = "No", "1" = "Yes"),
HeartDiseaseorAttack = recode(HeartDiseaseorAttack, "0" = "No", "1" = "Yes"),
PhysActivity = recode(PhysActivity, "0" = "No", "1" = "Yes"),
Fruits = recode(Fruits, "0" = "No", "1" = "Yes"),
Veggies = recode(Veggies, "0" = "No", "1" = "Yes")
)
#Diabetes status, Education and Income, etc labels
ddat2 <- ddat2 %>%
mutate(
Education = recode(Education,
"1" = "No High School",
"2" = "Some High School",
"3" = "High School Graduate",
"4" = "Some College",
"5" = "College Graduate",
"6" = "College 4 years or more (College graduate)"),
Income = recode(Income,
"1" = "<$10K",
"2" = "$10K-$15K",
"3" = "$15K-$25K",
"4" = "$25K-$35K",
"5" = "$35K-$50K",
"6" = "$50K-$75K",
"7" = ">$75K",
.default = "Unknown"),
Sex = recode(Sex,
"1" = "Male",
"0" = "Female",
.default = "Unknown"),
CholCheck = recode(CholCheck,
"1" = "Yes",
"0" = "No" ),
DiffWalk = recode(DiffWalk,
"1" = "Yes",
"0" = "No" ),
AnyHealthcare = recode(AnyHealthcare,
"1" = "Yes",
"0" = "No" ),
NoDocbcCost = recode(NoDocbcCost,
"1" = "Yes",
"0" = "No" ),
HvyAlcoholConsump = recode(HvyAlcoholConsump,
"1" = "Yes",
"0" = "No" ),
Diabetes_binary = recode(Diabetes_binary,
"0" = "No Diabetes",
"1" = "Has Diabetes"),
GenHlth = recode(GenHlth,
"1" = "Excellent",
"2" = "Very Good",
"3" = "Good",
"4" = "Fair",
"5" = "Poor",
.default = "Unknown")
)
#table (ddat2$Income)
#unique(ddat2$Income)
# create some missing data points
# Define the percentage of missing values
missing_percentage <- 0.05
# Get total number of rows
total_rows <- nrow(ddat2)
# Apply missing values to all variables
ddat2 <- ddat2 %>%
mutate(across(everything(), ~ {
miss_id <- sample(1:total_rows, size = round(missing_percentage * total_rows), replace = FALSE)
.[miss_id] <- NA # Assign NA to selected rows
.
}))
# overall summary of variables
library(summarytools)
dfSummary(ddat2)
#table(ddat2$Age)
#table(ddat2$BMI_Cat)
#summary (ddat2$BMI)
# get data into R
#BMI variable
library(ggplot2)
library(gridExtra)
library(grid)
bmi1 <- ggplot(ddat2, aes(x = BMI)) +
geom_histogram(binwidth = 2, fill = "steelblue", color = "black", alpha = 0.7) +
labs(title = "BMI Distribution", x = "BMI", y = "Count") +
theme_minimal()
bmi2 <- ggplot(ddat2, aes(x = BMI)) +
geom_density(fill = "lightblue", alpha = 0.6) +
labs(title = "Density Plot of BMI", x = "BMI", y = "Density") +
theme_minimal()
bmi3 <- ggplot(ddat2, aes(y = BMI)) +
geom_boxplot(fill = "tomato", alpha = 0.7, outlier.color = "red") +
labs(title = "Boxplot of BMI", y = "BMI") +
theme_minimal()
grid.arrange(bmi1, bmi2, bmi3, ncol = 2, top = textGrob("Overview of BMI", gp = gpar(fontsize = 16, fontface = "bold")))

#check skewness of BMI
library(e1071)
skewness(ddat2$BMI, na.rm=TRUE)
skewness(ddat2$BMI, na.rm=TRUE)
# remove BMI outliers
Q1 <- quantile(ddat2$BMI, 0.25, na.rm = TRUE)
Q3 <- quantile(ddat2$BMI, 0.75, na.rm = TRUE)
IQR <- Q3 - Q1
# Define acceptable range
lower_bound <- Q1 - 1.5 * IQR
upper_bound <- Q3 + 1.5 * IQR
# Remove outliers
ddat3 <- ddat2[ddat2$BMI >= lower_bound & ddat2$BMI <= upper_bound, ]
#plot of BMI with outliers removed: ddat3 now contains data with no outliers
bmi12 <- ggplot(ddat3, aes(x = BMI)) +
geom_histogram(binwidth = 2, fill = "steelblue", color = "black", alpha = 0.7) +
labs(title = "BMI Distribution", x = "BMI", y = "Count") +
theme_minimal()
bmi22 <- ggplot(ddat3, aes(x = BMI)) +
geom_density(fill = "lightblue", alpha = 0.6) +
labs(title = "Density Plot of BMI", x = "BMI", y = "Density") +
theme_minimal()
bmi32 <- ggplot(ddat3, aes(y = BMI)) +
geom_boxplot(fill = "tomato", alpha = 0.7, outlier.color = "red") +
labs(title = "Boxplot of BMI", y = "BMI") +
theme_minimal()
grid.arrange(bmi12, bmi22, bmi32, ncol = 2, top = textGrob("Overview of BMI with no outliers", gp = gpar(fontsize = 16, fontface = "bold")))

#categorized BMI bar chart
bmigrp<- ggplot(ddat3 %>% filter(!is.na(BMI_Cat)), aes(x = BMI_Cat)) +
geom_bar(fill = "lightblue" , width = 0.6) +
labs(title = "BMI Categories Distribution",
x = "BMI category",
y = "Count"
) +
theme_classic() +
theme(plot.margin = margin(2, 2, 2, 2) )
bmigrp

- Diabetes Status: In the sample, majority of the participants did not
have diabetes(86%). Only a smaller proportion where diabetic or had
pre-diabetes. This suggests low prevalence of diabetes in our
sample.
- Mental Health: Histogram and density plots showed few people had few
days with poor mental health the last 30 days (mean = approximately 3
days of bad mental health days). Outliers were replaced with mean
values.
- Physical Health in last 30 days distribution showed outliers and
these values were replaced with the mean.
- General Health Status: Most people reported very good or good health
status overall with skewness observed towards poor health. and so no
special changes will be applied to the variable.
- Income variable was negatively skewed. Most participants earned
higher income. The variable is categorized into Low, Medium, and High
income levels.
- Sex: More females participated in the sample data than males.
- Age: Distribution of age was such that majority of participants were
beyond 40 years old. This suggests that most participants were older and
age should controlled for in any analysis.
- Education: Most of the participants had a high school diploma or
higher (over 80%).
- High blood Pressure and High Cholesterol: More participants did not
have high blood pressure and more did not have any cholesterol checks in
the last 5 years.
- Smoker: About 44% of the participants smoked at least 100 cigarettes
in their entire lifetime. Considering how smoking affects our health and
with such many in sample, controlling for this variable in our analysis
and exploring how this variable interacts with others to impact diabetes
will be studied.
- Heavy Alcohol consumption - both men and women reported they are not
heavy drinkers but these could be incorrect representation due to the
fact that they may report as not heavy drinkers for socially desirable
responses and expectations. The analysis can be conducted for men and
women separately and for those who reported as heavy drinkers to uncover
hidden relations.
- Heart disease/attack was not prevalent in our sample. But we know
that diabetes impacts the heart function, it will be interesting to see
if those who had diabetes reported to ave had any of these
conditions.
- Stroke: Most people had never been told they had diabetes
(95%).
- Other variables: Most people did not have difficulty walking up the
stairs, were physically active in the past 30 days, had some form of
health insurance and could see a doctor when needed, consumed vegetables
once or more times a day, but slightly more did not consume fruits at
the same rate as vegetables.
# Diabetes Status
ggplot(ddat3 %>% filter(!is.na(Diabetes_binary)), aes(x = factor(Diabetes_binary))) +
geom_bar(fill = "lightblue" , width = 0.4) +
labs(title = "Diabetes Status",
x = "Diabetes Status",
y = "Count"
) +
theme_classic()+
theme(plot.margin = margin(2, 2, 2, 2) )

#Percentages within diabetes
Diab.percentages <- ddat3 %>%
count(Diabetes_binary) %>%
mutate(Percentage = n / sum(n) * 100)
Diab.percentages
#Mental Health Variables
summary(ddat3$MentHlth)
menh1 <- ggplot(ddat2, aes(x = MentHlth)) +
geom_density(fill = "yellow", alpha = 0.6) +
labs(title = "Density Plot of not good mental health days", x = "Mental Health", y = "Density") +
theme_minimal()
menh2 <- ggplot(ddat3, aes(x = MentHlth)) +
geom_histogram(binwidth = 2, fill = "yellow", color = "black", alpha = 0.7) +
labs(title = "Histogram of not good mental health days", x = "Days", y = "Count") +
theme_minimal()
menh3 <- ggplot(ddat3, aes(y = MentHlth)) +
geom_boxplot(fill = "yellow", alpha = 0.7, outlier.color = "red") +
labs(title = "Boxplot of Number of days Mental health was not good", y = "Mental Health Days") +
theme_minimal()
grid.arrange(menh1, menh2, menh3, ncol = 2, top = textGrob("Overview of Mental Health in Past 30 Days", gp = gpar(fontsize = 16, fontface = "bold")))

# Define a function to replace outliers with the mean
replace_outliers_with_mean <- function(x) {
Q1 <- quantile(x, 0.25, na.rm = TRUE)
Q3 <- quantile(x, 0.75, na.rm = TRUE)
IQR <- Q3 - Q1
# Define lower and upper bounds
lower_bound <- Q1 - 1.5 * IQR
upper_bound <- Q3 + 1.5 * IQR
# Replace outliers with the mean
x[x < lower_bound | x > upper_bound] <- mean(x, na.rm = TRUE)
return(x)
}
# Apply the function to mental health to replace outliers with mean value
ddat3$MentHlth <- replace_outliers_with_mean(ddat3$MentHlth)
#Physical Health histogram
Ph <- ggplot(ddat3, aes(x = PhysHlth)) +
geom_histogram(binwidth = 2, fill = "steelblue", color = "black", alpha = 0.7) +
labs(title = "Physical Health Days", x = "Days", y = "Count") +
theme_minimal()
#Ph
# Apply the function to mental health to replace outliers with mean value
ddat3$PhysHlth <- replace_outliers_with_mean(ddat3$PhysHlth)
#categorized General Health bar chart
ddat3 <- ddat3 %>%
mutate(GenHlth = factor(GenHlth,
levels = c("Poor", "Fair", "Good", "Very Good", "Excellent"),
ordered = TRUE))
Gh <- ggplot(ddat3 %>% filter(!is.na(GenHlth)), aes(x = GenHlth)) +
geom_bar(fill = "blue", width =0.4) +
labs(title = "General Health Status",
x = "General Health",
y = "Count"
) +
scale_x_discrete(expand = c(0.1, 0.1))+
theme_classic()
Gh

#categorized Sex chart
Sex <- ggplot(ddat3 %>% filter(!is.na(Sex)), aes(x = Sex)) +
geom_bar(fill = "blue") +
labs(title = "Gender",
x = "Gender",
y = "Count"
) +
theme_classic()
#Sex
unique(ddat3$Sex);
# Age Groups
Age <- ggplot(ddat2 %>% filter(!is.na(Age)), aes(x = Age)) +
geom_bar(fill = "blue") +
labs(title = "Age group Bar Chart",
x = "Age Group",
y = "Count"
) +
theme_classic()
#Age
Age.percentages <- ddat %>%
count(Age) %>%
mutate(Percentage = n / sum(n) * 100)
Age.percentages
# Education
Edu.percentages <- ddat %>%
count(Education) %>%
mutate(Percentage = n / sum(n) * 100)
Edu.percentages
# Smoker
Smoke.percentages <- ddat %>%
count(Smoker) %>%
mutate(Percentage = n / sum(n) * 100)
Smoke.percentages
# Stroke
Stroke.percentages <- ddat %>%
count(Stroke) %>%
mutate(Percentage = n / sum(n) * 100)
Stroke.percentages
4. Relationship between Features - Bivariate
We will now explore and have visualizations of relationships among
several variables in our sample data. We will be looking at visuals for
two or more numerical feature variables, categorical variables and
visuals that look combinations of these to aid in our understanding of
the data and how it influences our understanding of how to approach
analysis of the data.
- Diabetes and BMI plots : The box plot showing the diabetes and BMI
plot shows the median BMI in the diabetic group is higher suggests
relationship between these 2 variables. Additionally, the density plot
shows higher BMI in the diabetic group than the non-diabetic group.
- Diabetes and Physical Activity plot: The bivariate plot shows that
while the distribution of physical activity in the past 30 days is
similar, far less
diabetic people were physically active in the last 30 days.
########## two variable relationships
# diabetes and BMI
ggplot(ddat3%>% filter(!is.na(Diabetes_binary)), aes(x = factor(Diabetes_binary), y = BMI, fill = factor(Diabetes_binary))) +
geom_boxplot() +
labs(title = "BMI Distribution by Diabetes Status",
x = "Diabetes Status",
y = "BMI") +
scale_fill_manual(values = c("red", "green")) +
theme_classic()+
theme(legend.title = element_blank())

ggplot(ddat3%>% filter(!is.na(Diabetes_binary)), aes(x = BMI, fill = factor(Diabetes_binary))) +
geom_density(alpha = 0.5) +
labs(title = "BMI Density Plot by Diabetes Status",
x = "BMI",
y = "Density") +
scale_fill_manual(values = c("red", "green")) +
theme_minimal()+
theme(legend.title = element_blank())

#diabetes and physical health
ggplot(ddat3%>% filter(!is.na(Diabetes_binary) & !is.na(PhysActivity)), aes(x = factor(Diabetes_binary), fill = factor(PhysActivity))) +
geom_bar(position = "dodge") +
labs(title = "Grouped Bar Plot of Diabetes Status and Physical Activity in pas 30 days",
x = "Diabetes Status",
y = "Count") +
scale_fill_manual(values = c("blue", "red", "green")) +
guides(fill = guide_legend(title = "Pysically Active last 30 days")) +
theme_classic()

#colnames(ddat3)
#correlation plot of numerical variables
library(ggcorrplot)
select_vars <- c("PhysHlth", "MentHlth", "GenHlth", "BMI")
corr_matrix <- cor(ddat %>% select(all_of(select_vars)), use = "complete.obs")
library(ggplot2)
library(reshape2)
# Convert matrix to long format
corr_melt <- melt(corr_matrix)
# Plot heatmap
# Plot with text labels
cor1 <- ggplot(corr_melt, aes(x = Var1, y = Var2, fill = value)) +
geom_tile() +
geom_text(aes(label = round(value, 2)), color = "black", size = 4) + # Add values
scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = 0) +
theme_minimal() +
labs(title = "Correlation Heatmap", fill = "Correlation") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
#install.packages("corrplot")
library(corrplot)
corrplot(corr_matrix, method = "color", type = "upper",
col = colorRampPalette(c("blue", "white", "red"))(200),
tl.cex = 0.7, tl.col = "black",
addCoef.col = "black", number.cex = 0.8) # Add values

#install.packages("plotly")
library(ggplot2)
library(plotly)
unique(ddat3$Income_cat)
[1] Low Very High High Medium <NA>
Levels: Low Medium High Very High
mycolors <- c("Low" = "red", "Medium" = "orange", "High" = "green", "Very High" = "blue")
ggplotly_density <- ddat3%>% filter(!is.na(Income_cat) & !is.na(Diabetes_binary)) %>%
ggplot(aes(x = BMI, color = Income_cat, fill = Income_cat)) +
geom_density(linewidth = 0.75, alpha = 0.6) +
xlab("BMI Index") +
labs(color = "Income Groups", fill = "Income Groups") +
ggtitle("Density Curve of BMI across Income Groups") +
scale_color_manual(values = mycolors) + # Custom line colors
scale_fill_manual(values = mycolors) + # Custom fill colors
theme(plot.margin = unit(c(2,1,2,1), "cm"),
plot.title = element_text(hjust = 0.5)) +
facet_wrap(~ Diabetes_binary) # Split by diabetes status
ggplotly(ggplotly_density)
mycolors.n <- c("Poor" = "red", "Fair" = "orange", "Good" = "green", "Very Good" = "blue", "Excellent" = "lightblue")
ggplotly_density.n <- ddat3%>% filter(!is.na(GenHlth) & !is.na(Diabetes_binary)) %>%
ggplot(aes(x = BMI, color = GenHlth, fill = GenHlth)) +
geom_density(linewidth = 0.75, alpha = 0.6) +
xlab("BMI Index") +
labs(color = "General Health", fill = "General Health") +
ggtitle("Density Curve of BMI across General Health") +
scale_color_manual(values = mycolors.n) + # Custom line colors
scale_fill_manual(values = mycolors.n) + # Custom fill colors
theme(plot.margin = unit(c(2,1,2,1), "cm"),
plot.title = element_text(hjust = 0.5)) +
facet_wrap(~ Diabetes_binary) # Split by diabetes status
ggplotly(ggplotly_density.n)
LS0tCnRpdGxlOiAiSWRlbnRpZmljYXRpb24gb2YgRmFjdG9ycyBBc3NvY2ljYXRlZCB3aXRoIERpYWJldGVzIGluIHRoZSBVU0EiCiNzdWJ0aXRsZTogIkJlaGF2aW9yYWwgUmlzayBGYWN0b3IgU3VydmVpbGxhbmNlIFN5c3RlbSAoQlJGU1MpIgphdXRob3I6ICJNZXJjeSBBdHVhaGVuZSIgCmRhdGU6ICJGZWJydWFyeSA1LCAyMDI1IgphZmZpbGlhdGlvbjogIldlc3QgQ2hlc3RlciBVbml2ZXJzaXR5IG9mIFBlbm5zeWx2YW5pYSwgRGVwYXJ0bWVudCBvZiBTdGF0aXN0aWNzIgpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDogCiAgICB0b2M6IHllcwogICAgdG9jX2RlcHRoOiA0CiAgICB0b2NfZmxvYXQ6IHllcwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgdG9jX2NvbGxhcHNlZDogeWVzCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgc21vb3RoX3Njcm9sbDogeWVzCiAgICB0aGVtZTogbHVtZW4KIAogIHdvcmRfZG9jdW1lbnQ6IAogICAgdG9jOiB5ZXMKICAgIHRvY19kZXB0aDogNAogICAgZmlnX2NhcHRpb246IHllcwogICAga2VlcF9tZDogeWVzCiAgcGRmX2RvY3VtZW50OiAKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDQKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogbm8KICAgIGZpZ193aWR0aDogMwogICAgZmlnX2hlaWdodDogMwplZGl0b3Jfb3B0aW9uczogCiAgY2h1bmtfb3V0cHV0X3R5cGU6IGlubGluZQotLS0KCmBgYHs9aHRtbH0KCjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+CgovKiBDYXNjYWRpbmcgU3R5bGUgU2hlZXRzIChDU1MpIGlzIGEgc3R5bGVzaGVldCBsYW5ndWFnZSB1c2VkIHRvIGRlc2NyaWJlIHRoZSBwcmVzZW50YXRpb24gb2YgYSBkb2N1bWVudCB3cml0dGVuIGluIEhUTUwgb3IgWE1MLiBpdCBpcyBhIHNpbXBsZSBtZWNoYW5pc20gZm9yIGFkZGluZyBzdHlsZSAoZS5nLiwgZm9udHMsIGNvbG9ycywgc3BhY2luZykgdG8gV2ViIGRvY3VtZW50cy4gKi8KCmgxLnRpdGxlIHsgIC8qIFRpdGxlIC0gZm9udCBzcGVjaWZpY2F0aW9ucyBvZiB0aGUgcmVwb3J0IHRpdGxlICovCiAgZm9udC1zaXplOiAyMnB4OwogIGZvbnQtd2VpZ2h0OiBib2xkOwogIGNvbG9yOiBEYXJrUmVkOwogIHRleHQtYWxpZ246IGNlbnRlcjsKICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7Cn0KaDQuYXV0aG9yIHsgLyogSGVhZGVyIDQgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciBhdXRob3JzICAqLwogIGZvbnQtc2l6ZTogMThweDsKICBmb250LXdlaWdodDogYm9sZDsKICBmb250LWZhbWlseTogc3lzdGVtLXVpOwogIGNvbG9yOiBuYXZ5OwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQpoNC5kYXRlIHsgLyogSGVhZGVyIDQgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciB0aGUgZGF0ZSAgKi8KICBmb250LXNpemU6IDE4cHg7CiAgZm9udC1mYW1pbHk6IHN5c3RlbS11aTsKICBjb2xvcjogRGFya0JsdWU7CiAgdGV4dC1hbGlnbjogY2VudGVyOwogIGZvbnQtd2VpZ2h0OiBib2xkOwp9CmgxIHsgLyogSGVhZGVyIDEgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciBsZXZlbCAxIHNlY3Rpb24gdGl0bGUgICovCiAgICBmb250LXNpemU6IDE4cHg7CiAgICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7CiAgICBjb2xvcjogbmF2eTsKICAgIHRleHQtYWxpZ246IGNlbnRlcjsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwp9CmgyIHsgLyogSGVhZGVyIDIgLSBmb250IHNwZWNpZmljYXRpb25zIGZvciBsZXZlbCAyIHNlY3Rpb24gdGl0bGUgKi8KICAgIGZvbnQtc2l6ZTogMTZweDsKICAgIGZvbnQtZmFtaWx5OiAiR2lsbCBTYW5zIiwgc2Fucy1zZXJpZjsKICAgIGNvbG9yOiBuYXZ5OwogICAgdGV4dC1hbGlnbjogbGVmdDsKICAgIGZvbnQtd2VpZ2h0OiBib2xkOwp9CgoKaDMgeyAvKiBIZWFkZXIgMyAtIGZvbnQgc3BlY2lmaWNhdGlvbnMgb2YgbGV2ZWwgMyBzZWN0aW9uIHRpdGxlICAqLwogICAgZm9udC1zaXplOiAxNHB4OwogICAgZm9udC1mYW1pbHk6ICJHaWxsIFNhbnMiLCBzYW5zLXNlcmlmOwogICAgY29sb3I6IG5hdnk7CiAgICB0ZXh0LWFsaWduOiBsZWZ0Owp9CgpoNCB7IC8qIEhlYWRlciA0IC0gZm9udCBzcGVjaWZpY2F0aW9ucyBvZiBsZXZlbCA0IHNlY3Rpb24gdGl0bGUgICovCiAgICBmb250LXNpemU6IDEycHg7CiAgICBmb250LWZhbWlseTogIkdpbGwgU2FucyIsIHNhbnMtc2VyaWY7CiAgICBjb2xvcjogZGFya3JlZDsKICAgIHRleHQtYWxpZ246IGxlZnQ7Cn0KCmJvZHkgeyBiYWNrZ3JvdW5kLWNvbG9yOndoaXRlOyB9CgouaGlnaGxpZ2h0bWUgeyBiYWNrZ3JvdW5kLWNvbG9yOnllbGxvdzsgfQoKcCB7IGJhY2tncm91bmQtY29sb3I6d2hpdGU7IH0KCjwvc3R5bGU+CmBgYAoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CgojIGNvZGUgY2h1bmsgc3BlY2lmaWVzIHdoZXRoZXIgdGhlIFIgY29kZSwgd2FybmluZ3MsIGFuZCBvdXRwdXQgCiMgd2lsbCBiZSBpbmNsdWRlZCBpbiB0aGUgb3V0cHV0IGZpbGVzLgppZiAoIXJlcXVpcmUoImtuaXRyIikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygia25pdHIiKQogICBsaWJyYXJ5KGtuaXRyKQp9CmlmICghcmVxdWlyZSgidGlkeXZlcnNlIikpIHsKICAgaW5zdGFsbC5wYWNrYWdlcygidGlkeXZlcnNlIikKbGlicmFyeSh0aWR5dmVyc2UpCn0KaWYgKCFyZXF1aXJlKCJHR2FsbHkiKSkgewogICBpbnN0YWxsLnBhY2thZ2VzKCJHR2FsbHkiKQpsaWJyYXJ5KEdHYWxseSkKfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsICAgIyBpbmNsdWRlIGNvZGUgY2h1bmsgaW4gdGhlIG91dHB1dCBmaWxlCiAgICAgICAgICAgICAgICAgICAgICB3YXJuaW5nID0gRkFMU0UsIyBzb21ldGltZXMsIHlvdSBjb2RlIG1heSBwcm9kdWNlIHdhcm5pbmcgbWVzc2FnZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB5b3UgY2FuIGNob29zZSB0byBpbmNsdWRlIHRoZSB3YXJuaW5nIG1lc3NhZ2VzIGluCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIyB0aGUgb3V0cHV0IGZpbGUuIAogICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFRSVUUsICMgeW91IGNhbiBhbHNvIGRlY2lkZSB3aGV0aGVyIHRvIGluY2x1ZGUgdGhlIG91dHB1dAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICMgaW4gdGhlIG91dHB1dCBmaWxlLgogICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgY29tbWVudCA9IE5BCiAgICAgICAgICAgICAgICAgICAgICApICAKI3NldHdkKCJ+IikKI3NldHdkKCIvVXNlcnMvbWthdHVhaGVuZS9EZXNrdG9wL1dDVS9SLU1hY2hpbmUgTGVhcm5pbmcvQXNzaWdubWVudC9XZWVrIDIiKSAKYGBgCgpcCgojIyAxLiBBYnN0cmFjdApUaGlzIGFuYWx5c2lzIHN0dWRpZXMgdGhlIHJlbGF0aW9uc2hpcHMgYW1vbmcgaGVhbHRoIGluZGljYXRvcnMgYW5kIGRpYWJldGVzIHN0YXR1cyB2aWEgZXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcyB2aXN1YWxpemF0aW9ucy4gSXQgaXMgYmFzZWQgb24gYSBzYW1wbGUgZGF0YSBmcm9tIHRoZSBEaWFiZXRlcyBIZWFsdGggSW5kaWN0b3JzIGRhdGFzZXQgKEJSRlNTIDIwMTUpLiBXZSBmaXJzdCB1c2UgdmlzdWFsaXphdGlvbiBtZXRob2RzIHRvIGxvb2sgYXQgaW5kaXZpZHVhbCB2YXJpYWJsZSBkaXN0cmlidXRpb25zIGFuZCB0aGVuIGV4YW1pbmUgYXNzb2NpYXRpb25zIGJldHdlZW4gZGlmZmVyZW50IHR5cGVzIG9mIHZhcmlhYmxlcyBsaWtlIGRpYWJldGVzIHN0YXR1cyBhbmQgQk1JIHRocm91Z2ggaGlzdG9ncmFtcywgYm94IHBsb3RzIGFuZCBkZW5zaXR5IHBsb3RzLiBXZSBhbHNvIGV4cGxvcmVkIHJlbGF0aW9ucyBiZXR3ZWVuIG51bWVyaWNhbCB2YXJpYWJsZXMgYW5kIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyB2aWEgYm94IHBsb3RzIHRvIGlsbHVzdHJhdGUgaG93IGRpc3RyaWJ1dGlvbnMgb2YgQk1JIHZhcnkgYWNyb3NzIGRpYWJldGVzIGdyb3Vwcy4gV2UgYWxzbyBsb29rZWQgYXQgaGlnaCBkaW1lbnNpb25hbCByZWxhdGlvbnMgdXNpbmcgZmFjZXRlZCBhbmQgaW50ZXJhY3RpdmUgcGxvdHMuIFRvZ2V0aGVyLCB0aGVzZSBwcm92aWRlZCBwcmVsaW1pbmFyeSBpbnNpZ2h0cyBpbnRvIHRoZSBwYXR0ZXJucyBvZiByZWxhdGlvbnNoaXBzIHRoYXQgZXhpc3QgaW4gdGhlIGRhdGFzZXQgYW5kIGhlbHAgZXhwbGFpbiBmYWN0b3JzIGFzc29jaWF0ZWQgd2l0aCBkaWFiZXRlcyBmb3IgZnVydGhlciBhbmFseXNpcy4gIAoKClwKCiMjIDIuIEludHJvZHVjdGlvbgogIEluIHRoZSBVU0EsIGRpYWJldGVzIGltcGFjdHMgb3ZlciAzNyBtaWxsaW9uIEFtZXJpY2FucyBhbmQgMSBpbiA1IHBlb3BsZSB3aXRoIGRpYWJldGVzIGRvIG5vdCBrbm93IHRoZXkgaGF2ZSBpdCBhY2NvcmRpbmcgdG8gdGhlIENEQy4gT3ZlciAzOCUgb2YgdGhlIFVTIHBvcHVsYXRpb24gaGF2ZSBwcmUtZGlhYmV0ZXMgLSBhIGNvbmRpdGlvbiB0aGF0IGluY3JlYXNlcyB0aGUgcmlzayBvZiBkZXZlbG9waW5nIHR5cGUgMiBkaWFiZXRlcy4gSXQgaXMgb25lIG9mIHRoZSBtb3N0IHByZXZhbGVudCBjaHJvbmljIGRpc2Vhc2VzIGluIHRoZSBVUyA8YSAgIGhyZWY9Imh0dHBzOi8vd3d3LmNkYy5nb3YvcGNkL2lzc3Vlcy8yMDE5LzE5XzAxMDkuaHRtIiB0YXJnZXQ9Il9ibGFuayI+IFhpZSBldCBhbCAoMjAxOSk8L2E+IC4gVGhpcyBwcmVzZW50cyBhIHB1YmxpYyBoZWFsdGggaXNzdWUgdGhhdCBoYXMgZWNvbm9taWMgYnVyZGVucywgaW5jcmVhc2VkIG1vcnRhbGl0eSByYXRlcyBhbmQgb3RoZXIgaGVhbHRoIGNvbXBsaWNhdGlvbnMuIEl0IGlzIGVzdGltYXRlZCB0aGF0IHRoZSBlY29ub21pYyBidXJkZW4gb2YgZGlhYmV0ZXMgaW4gdGhlIFVTIGlzIGFib3V0ICQzMjcgYmlsbGlvbiBhbnVhbGx5IHdpdGggdGhlIGNvc3Qgb2YgY2FyZSBvbiB0aGUgcmlzZS4gV2l0aCBhIHJpc2UgaW4gdGhlIG51bWJlciBvZiBkaWFiZXRlcyBjYXNlcyBpbiByZWNlbnQgeWVhcnMgYW5kIGl0cyBlY29ub21pYyBidXJkZW4sIHVuZGVyc3RhbmRpbmcgb2YgcmlzayBmYWN0b3JzIGRyaXZpbmcgdGhlc2UgbnVtYmVycyBhcmUgZXNzZW50aWFsIHRvIGVuYWJsZSBwb2xpY2llcyB0aGF0IGludGVydmVuZSBvbiB0aGlzIG5hdGlvbmFsIGhlYWx0aCBjcmlzZXMuIFRyYWNraW5nIG9mIGNhc2VzIGJ5IHRoZSBCUkZTUyBpcyBvbmUgd2F5IHRoZSBVUyBpcyB1c2luZyB0byBjdXJiIGRpYWJldGVzIHByZXZhbGVuY2UgYW5kIGl0cyBhc3NvY2lhdGVkIHJpc2sgZmFjdG9ycyBhbmQgYWxzbyB0byBpbnRlcnZlbmUgb24gbW9kaWZpYWJsZSBsaWZlc3R5bGUgY2hvaWNlcy4gRm9yIG1vcmUgZGV0YWlscywgdmlzaXQgPGEgaHJlZj0iaHR0cHM6Ly93d3cuY2RjLmdvdi9kaWFiZXRlcy9hYm91dC9pbmRleC5odG1sP3V0bV9zb3VyY2U9Y2hhdGdwdC5jb20jY2RjX2Rpc2Vhc2VfYmFzaWNzX3F1aWNrX2ZhY3RzX2NhbGxvdXRfY2FsbG91dC1kaWFiZXRlcy1ieS10aGUtbnVtYmVycyIgdGFyZ2V0PSJfYmxhbmsiPkRpYWJldGVzIEJhc2ljczwvYT4gCgpUaGUgQmVoYXZpb3JhbCBSaXNrIEZhY3RvciBTdXJ2ZWlsbGFuY2UgU3lzdGVtIChCUkZTUykgaXMgYSB0ZWxlcGhvbmUgc3VydmV5IGNvbmR1Y3RlZCBhbm51YWxseSBieSB0aGUgQ2VudGVyIEZvciBEaXNlYXNlIENvbnRyb2wgYW5kIFByZXZlbnRpb24gKENEQykgdG8gY29sbGVjdCB1bmlmb3JtLCBzdGF0ZS1zcGVjaWZpYyBkYXRhIG9uIFVTIGFkdWx0cycgaGVhbHRoLXJlbGF0ZWQgcmlzayBiZWhhdmlvcnMsIGNocm9uaWMgaGVhbHRoIGNvbmRpdGlvbnMgbGlrZSBkaWFiZXRlcywgYW5kIHVzZSBvZiBwcmV2ZW50aXZlIHNlcnZpY2VzLiBUaGUgZm9jdXMgb2YgdGhlIHN1cnZleSBpcyB0byBjb2xsZWN0IGRhdGEgb24gZGVtb2dyYXBoaWNzIGFuZCBzb2NpYWwgZGV0ZXJtaW5hbnRzIG9mIGhlYWx0aCwgbWVudGFsIGhlYWx0aCBhbmQgd2VsbCBiZWluZywgaGVhbHRoIHJpc2sgYmVoYXZpb3JzLCBjaHJvbmljIGhlYWx0aCBjb25kaXRpb25zIGFuZCB1c2Ugb2YgcHJldmVudGl2ZSBzZXJ2aWNlcyBpbiB0aGUgVW5pdGVkIFN0YXRlcyBwb3B1bGF0aW9uLiBJdCBpcyBhbiBpbXBvcnRhbnQgc3lzdGVtIHRoYXQgaGVscHMgcHVibGljIGhlYWx0aCBwZXJzb25uZWwgdG8gZGVzaWduIHBvbGljaWVzIGFuZCBoZWFsdGggcHJvZ3JhbXMgdGhhdCBiZW5lZml0cyBzdGF0ZXMgYW5kIGxvY2FsIGFnZW5jaWVzLiBEYXRhIGZyb20gdGhlIHN5c3RlbSBhbmQgdGhlIGN1cnJlbnQgYW5hbHlzaXMgaXMgdXRpbGl6ZWQgaW4gdGhlIGlkZW50aWZpY2F0aW9uIG9mIHJpc2sgZmFjdG9ycyB0aGF0IGNvbnRyaWJ1dGUgdG8gY2hyb25pYyBkaXNlYXNlcyBhbmQgaGVhbHRoIGRpc3Bhcml0aWVzIGFtb25nIGRpZmZlcmVudCBwb3B1bGF0aW9ucywgZXRjLiBXZSB3aWxsIHBhcnRpY3VsYXJpdHksIGV4cGxvcmUgdGhlIGFiaWxpdHkgdG8gaWRlbnRpZnkgd2hpY2ggZmVhdHVyZSB2YXJpYWJsZXMgaW4gdGhlIGRhdGEgYXJlIGFzc29jaWF0ZWQgd2l0aCBkaWFiZXRlcyBlaXRoZXIgYWxvbmUgb3IgaW4gY29tYmluYXRpb24gd2l0aCBvdGhlciByaXNrIGZhY3RvcnMgYW5kIGFsc28gdXNlIGFkdmFuY2UgbWV0aG9kcyBpbiBtYWNoaW5lIGxlYXJuaW5nIHRvIGFjY3VyYXRlbHkgcHJlZGljdCB3aGljaCBpbmRpdmlkdWFscyBoYXZlIGRpYWJldGVzIGJhc2VkIG9uIHRoZSByaXNrIGZhY3RvcnMgcmVwb3J0ZWQgaW4gdGhlIGxpdGVyYXR1cmUuIAoKCiogKipEZXNjcmlwdGlvbiBvZiBEYXRhKioKCiAgV2Ugd2lsbCB1c2UgdGhlIDIwMTUgQlJGU1MgZGF0YSBpbiBvdXIgZXhwbG9yYXRvcnkgYW5hbHlzaXMgb2YgdGhlIGZlYXR1cmUgdmFyaWFibGVzIGluIHRoaXMgZGF0YXNldC4gVGhlIGRhdGFzZXQgY29udGFpbnMgY2xlYW4gZGF0YSBvcmlnaW5hdGluZyBmcm9tIHRoZSBvcmlnaW5hbCBkYXRhc2V0IHdoaWNoIGNvbnRhaW5lZCA0NDEsIDQ1NSBpbmRpdmlkdWFscyBhbmQgaGFzIDMzMCBmZWF0dXJlcy4gVGhlIGNsZWFuIHZlcnNpb24gY29udGFpbnMgMjUzLDY4MSBzdXJ2ZXkgcmVzcG9uc2VzIGZyb20gdGhlIENEQydzIEJSRlNTIDIwMTUuIEl0IGNvbnRhaW5zIDIxIGZlYXR1cmUgdmFyaWFibGVzIGFuZCBvYnRhaW5lZCBmcm9tIHRoZSBrYWdnbGUgd2Vic2l0ZSA8YSAgIGhyZWY9Imh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvYWxleHRlYm91bC9kaWFiZXRlcy1oZWFsdGgtaW5kaWNhdG9ycy1kYXRhc2V0P3V0bV9zb3VyY2U9Y2hhdGdwdC5jb20mc2VsZWN0PWRpYWJldGVzX2IgICBpbmFyeV9oZWFsdGhfaW5kaWNhdG9yc19CUkZTUzIwMTUuY3N2IiB0YXJnZXQ9Il9ibGFuayI+RGlhYmV0ZXMgSGVhbHRoIEluZGljYXRvcnMgRGF0YXNldDwvYT4KCiogKipGZWF0dXJlIFZhcmlhYmxlcyoqCgogIFRoZSBjbGVhbiBkYXRhc2V0IChCUkZTUzIwMTUpIGNvbnRhaW5zIHRoZSBmb2xsb3dpbmcgZmVhdHVyZXMKICAgKiAqKlRhcmdldCBmZWF0dXJlOioqIGEgY2F0ZWdvcmljYWwgZmVhdHVyZSBpbmRpY2F0aW5nIGlmIGFuIGluZGl2aWR1YWwgaGFzIGRpYWJldGVzIG9yIG5vdCwgRGlhYmV0ZXNfYmluYXJ5ICgwID0gbm8gZGlhYmV0ZXMsIDEgPSBwcmVkaWFiZXRlcyBvciBkaWFiZXRlcykKICAgCiAgICogKipJbmRlcGVuZGVudCB2YXJpYWJsZXMqKgogICAgICsgSGlnaEJQOiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgKDAgPSBubyBoaWdoIEJQLCAxID0gaGlnaCBCUCkKICAgICArIEhpZ2hDaG9sOiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgdGhhdCBpbmRpY2F0ZXMgaWYgYW4gaW5kaXZpZHVhbCBoYXMgaGlnaCBjaG9sZXN0ZXJvbCAoMSA9IFllcywgMCA9IE5vKQogICAgICsgQ2hvbENoZWNrOiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgdGhhdCBpbmRpY2F0ZXMgaWYgYW4gaW5kaXZpZHVhbCBoYWQgdGhlaXIgY2hvbGVzdGVyb2wgY2hlY2tlZCBpbiB0aGUgcGFzdCBmaXZlIHllYXJzICgxID0gWWVzLCAwID0gTm8pCiAgICAgKyBCTUk6IEJvZHkgTWFzcyBJbmRleCxhIGNvbnRpbnVvdXMgbnVtZXJpY2FsIGZlYXR1cmUgYmFzZWQgb24gdGhlIG1lYXN1cmUgb2YgYm9keSBmYXQgYmFzZWQgb24gaGVpZ2h0IGFuZCB3ZWlnaHQKICAgICArIFNtb2tlcjogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIGlmIGFuIGluZGl2aWR1YWwgaGFzIHNtb2tlZCBhdCBsZWFzdCAxMDAgY2lnYXJldHRlcyBpbiB0aGVpciBsaWZldGltZSAoMSA9IFllcywgMCA9IE5vKQogICAgICsgU3Ryb2tlOiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgdGhhdCBpbmRpY2F0ZXMgaWYgYW4gaW5kaXZpZHVhbCBoYXMgaGFkIGEgc3Ryb2tlICgxID0gWWVzLCAwID0gTm8pCiAgICAgKyBIZWFydERpc2Vhc2VvckF0dGFjazogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIGlmIGFuIGluZGl2aWR1YWwgaGFzIGNvcm9uYXJ5IGhlYXJ0IGRpc2Vhc2Ugb3IgYSBoZWFydCBhdHRhY2sgKDEgPSBZZXMsIDAgPSBObykKICAgICArIFBoeXNBY3Rpdml0eTogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIGlmIGFuIGluZGl2aWR1YWwgaGFzIGVuZ2FnZWQgaW4gcGh5c2ljYWwgYWN0aXZpdHkgaW4gdGhlIHBhc3QgMzAgZGF5cyAoMSA9IFllcywgMCA9IE5vKQogICAgICsgRnJ1aXRzOiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgdGhhdCBpbmRpY2F0ZXMgaWYgdGhlIGluZGl2aWR1YWwgY29uc3VtZXMgZnJ1aXRzIGF0IGxlYXN0IG9uY2UgcGVyIGRheSAoMSA9IFllcywgMCA9IE5vKQogICAgICsgVmVnZ2llczogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIGlmIHRoZSBpbmRpdmlkdWFsIGNvbnN1bWVzIHZlZ2V0YWJsZXMgYXQgbGVhc3Qgb25jZSBwZXIgZGF5ICgxID0gWWVzLCAwID0gTm8pCiAgICAgKyBIdnlBbGNvaG9sQ29uc3VtcDogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIGhlYXZ5IGFsY29ob2wgY29uc3VtcHRpb24gKDEgPSBZZXMsIDAgPSBObykKICAgICArIEFueUhlYWx0aGNhcmU6IGEgY2F0ZWdvcmljYWwgZmVhdHVyZSB0aGF0IGluZGljYXRlcyBpZiB0aGUgaW5kaXZpZHVhbCBoYXMgYW55IGtpbmQgb2YgaGVhbHRoIGNhcmUgY292ZXJhZ2UgKDEgPSBZZXMsIDAgPSBObykKICAgICArIE5vRG9jYmNDb3N0OiBhIGNhdGVnb3JpY2FsIGZlYXR1cmUgdGhhdCBpbmRpY2F0ZXMgaWYgdGhlIGluZGl2aWR1YWwgY291bGQgbm90IHNlZSBhIGRvY3RvciBkdWUgdG8gY29zdCBpbiB0aGUgcGFzdCAxMiBtb250aHMgKDEgPSBZZXMsIDAgPSBObykKICAgICArIEdlbkhsdGg6IGEgY2F0ZWdvcmljYWwgZmVhdHVyZSB0aGF0IGluZGljYXRlcyBHZW5lcmFsIGhlYWx0aCBzdGF0dXMgKDEgPSBFeGNlbGxlbnQsIDIgPSBWZXJ5IGdvb2QsIDMgPSBHb29kLCA0ID0gRmFpciwgNSA9IFBvb3IpCiAgICAgKyBNZW50SGx0aDogYSBudW1lcmljYWwgZmVhdHVyZSByZXByZXNlbnRpbmcgdGhlIG51bWJlciBvZiBkYXlzIG1lbnRhbCBoZWFsdGggd2FzIG5vdCBnb29kIGluIHRoZSBwYXN0IDMwIGRheXMKICAgICArIFBoeXNIbHRoOiBhIG51bWVyaWNhbCBudW1lcmljYWwgZmVhdHVyZSByZXByZXNlbnRpbmcgdGhlIG51bWJlciBvZiBkYXlzIHBoeXNpY2FsIGhlYWx0aCB3YXMgbm90IGdvb2QgaW4gdGhlIHBhc3QgMzAgZGF5cwogICAgICsgRGlmZldhbGs6IGEgY2F0ZWdvcmljYWwgaW5kaWNhdGVzIGlmIHRoZSBpbmRpdmlkdWFsIGhhcyBzZXJpb3VzIGRpZmZpY3VsdHkgd2Fsa2luZyBvciBjbGltYmluZyBzdGFpcnMgKDEgPSBZZXMsIDAgPSBObykKICAgICArIFNleDogYSBjYXRlZ29yaWNhbCBmZWF0dXJlIHRoYXQgaW5kaWNhdGVzIHRoZSBnZW5kZXIgb2YgYW4gaW5kaXZpZHVhbCAoMSA9IE1hbGUsIDAgPSBGZW1hbGUpCiAgICAgKyBBZ2U6IGEgY2F0ZWdvcmljYWwgZmVhdHVyZSByZXByZXNlbnRpbmcgdGhlIGFnZSBjYXRlZ29yeSBvZiB0aGUgaW5kaXZpZHVhbCAoMSA9IDE44oCTMjQsIDIgPSAyNeKAkzI5LCAzID0gMzDigJMzNCwgNCA9IDM14oCTMzksIDUgPSA0MOKAkzQ0LCA2ID0gNDXigJM0OSwgNyA9IDUw4oCTNTQsIDggPSA1NeKAkzU5LCA5ID0gICAgICAgICAgICA2MOKAkzY0LCAxMCA9IDY14oCTNjksIDExID0gNzDigJM3NCwgMTIgPSA3NeKAkzc5LCAxMyA9IDgwIG9yIG9sZGVyKQogICAgICsgRWR1Y2F0aW9uOiBhIGNhdGVnb3JpY2FsIHZhcmlhYmxlIHRoYXQgaW5kaWNhdGVzIEVkdWNhdGlvbiBsZXZlbCBvZiB0aGUgaW5kaXZpZHVhbCAoMSA9IE5ldmVyIGF0dGVuZGVkIHNjaG9vbCBvciBvbmx5IGtpbmRlcmdhcnRlbiwgMiA9IEdyYWRlcyAxIHRocm91Z2ggOCAoRWxlbWVudGFyeSksIDMgPSAgICAgICAgR3JhZGVzIDkgdGhyb3VnaCAxMSAoU29tZSBoaWdoIHNjaG9vbCwgbm8gZGlwbG9tYSksIDQgPSBHcmFkZSAxMiBvciBHRUQgKEhpZ2ggc2Nob29sIGdyYWR1YXRlKSwgNSA9IENvbGxlZ2UgMSB0byAzIHllYXJzIChTb21lIGNvbGxlZ2Ugb3IgdGVjaG5pY2FsIHNjaG9vbCksIDYgPSBDb2xsZWdlIDQgICAgICAgIHllYXJzIG9yIG1vcmUgKENvbGxlZ2UgZ3JhZHVhdGUpICkKICAgICArIEluY29tZTogYSBjYXRlZ29yaWNhbCB2YXJpYWJsZSB0aGF0IGluZGljYXRlcyBJbmNvbWUgY2F0ZWdvcnkgb2YgdGhlIGluZGl2aWR1YWwgKCAxID0gTGVzcyB0aGFuICQxMCwwMDAsIDIgPSAgJDEwLDAwMCB0byAkMTQsOTk5LCAzID0gJDE1LDAwMCB0byAkMTksOTk5LCA0ID0gJDIwLDAwMCB0byAgICAgICAgICAgJDI0LDk5OSwgNSA9ICQyNSwwMDAgdG8gJDM0LDk5OSwgNiA9ICQzNSwwMDAgdG8gJDQ5LDk5OSwgNyA9ICQ1MCwwMDAgdG8gJDc0LDk5OSwgOCA9ICQ3NSwwMDAgb3IgbW9yZSkKClwKCiMjIDMuIERpc3RyaWJ1dGlvbiBvZiBJbmRpdmlkdWFsIEZlYXR1cmVzCgpcClRvIHByZXBhcmUgdGhlIGRhdGFzZXQgZm9yIG91ciBhbmFseXNpcyBwdXJwb3NlLCB3ZSB1dGlsaXplZCB0aGUgc2FtcGxlIGZ1bmN0aW9uIHRvIGNyZWF0ZSBzb21lIG1pc3NpbmduZXNzIGluIG91ciBkYXRhc2V0LiBXZSByYW5kb21seSByZXBsYWNlZCA1JSBvZiBhbGwgZmVhdHVyZSB2YXJpYWJsZXMgd2l0aCBtaXNzaW5nIHZhbHVlcyB0byBtYWtlIHRoZSBkYXRhc2V0IHJlcHJlc2VudCByZWFsIHdvcmxkIGRhdGEgd2hpY2ggaXMgb2Z0ZW4gb2JzZXJ2ZWQgd2l0aCBtaXNzaW5nIHZhbHVlcyBpbiB2YXJpYWJsZXMuICBJdCBpcyBpbXBvcnRhbnQgdG8gcG9pbnQgb3V0IHRoYXQgc2luY2UgdGhpcyBpcyBhbiBhbHJlYWR5IGNsZWFuZWQgZGF0YXNldCwgdGhlcmUgYXJlIG5vdCBtdWNoIHRvIGJlIGRvbmUgaW4gYWRkcmVzc2luZyBpc3N1ZXMgbGlrZSB1bmxpa2VseSB2YWx1ZXMgKCBleHRyZW1lIGhlaWdodCBvciB3ZWlnaHQsIGV0Yywgbm9uIHN0YW5kYXJkIHJlc3BvbnNlIHRvIHF1ZXN0aW9ubmFpcmVzIGFtb25nIG90aGVycykuIFdlIHdpbGwgdXRpbGl6ZSBleHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzIHRvIHVuY292ZXIgcGF0dGVybnMgYW5kIHJlbGF0aW9uc2hpcHMgaW4gdGhlIGRhdGFzZXQuIEZlYXR1cmUgZW5naW5lZXJpbmcgd2lsbCBiZSBhcHBsaWVkIHdoZXJlIGFwcGxpY2FibGUgdG8gY3JlYXRlIG5ldyB2YXJpYWJsZXMgYW5kIGEgdmlzdWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkYXRhIHdpbGwgYmUgcHJvdmlkZWQgdG8gaWRlbnRpZnkgdHJlbmRzIGFuZCBmZWF0dXJlIHZhcmlhYmxlIGRpc3RyaWJ1dGlvbnMuIEFkZGl0aW9uYWxseSwgc3ViIGdyb3VwIHZpc3VhbGl6YXRpb25zIHdpbGwgYmUgcHJlc2VudGVkIHRoYXQgZW5saWdodGVucyBvdXIgdW5kZXJzdGFuZGluZyBvZiBob3cgZGlhYmV0ZXMgYWZmZWN0cyBjZXJ0YWluIGdyb3VwcyBvZiBwZW9wbGUgYW5kIHdoaWNoIGZlYXR1cmUgdmFyaWFibGVzIGFyZSBhc3NvY2lhdGVkIHdpdGggZGlhYmV0ZXMuIAoKKiAqKkluZGl2aWR1YWwgYW5hbHl0aWMgdGFza3MqKiAtClRoZSBmb2xsb3dpbmcgZmVhdHVyZSB2YXJpYWJsZXMgY29tcHJpc2Ugb2Ygc29tZSBvZiB0aGUgcmlzayBmYWN0b3JzIHRoYXQgYXJlIHJlcG9ydGVkIHRvIGJlIGFzc29jaWF0ZWQgd2l0aCBkaWFiZXRlcyB0aGF0IHdpbGwgYmUgc3R1ZGllZC4KICArIEJNSTogQk1JIGhpc3RvZ3JhbSBzaG93ZWQgcG9zaXRpdmVseSBza2V3ZWQgZGF0YSB3aGlsZSBhIGJveCBwbG90IGFsc28gc2hvd2VkIG91dGxpZXJzLiBUaGUgb3V0bGllcnMgd2VyZSByZW1vdmVkIGZyb20gdGhlIGRhdGFzZXQgdGhhdCB3ZXJlIDEuNSB0aW1lcyBsb3dlciBvciBoaWdoZXIgdGhhbiB0aGUgICAgIGZpcnN0IGFuZCB0aGlyZCBxdWFydGlsZXMuIFRoZSBwbG90IG9mIHRoZSBkYXRhIHdpdGhvdXQgdGhlIG91dGxpZXJzIHNob3dlZCBhIHNtb290aGVyIGRpc3RyaWJ1dGlvbi4KICAgIEJNSSB3YXMgcmUtY2F0ZWdvcml6ZWQgaW50byBVbmRlcndlaWdodCwgTm9ybWFsLCBPdmVyd2VpZ2h0IGFuZCBPYmVzZS4gT3ZlciA3MCUgb2YgdGhlIHNhbXBsZSB3ZXJlIGVpdGhlciBvdmVyd2VpZ2h0IG9yIG9iZXNlIHRvIGhlbHAgaWRlbnRpZnkgYXQgcmlzayBwb3B1bGF0aW9ucyBhbmQgZWFzaWVyIGludGVycHJldGF0aW9uIG9mIHRoZSBkYXRhIGFuZCBmb3IgdHJlbmQgaWRlbnRpZmljYXRpb24uIEl0IHdhcyBhcHBhcmVudCB0aGF0IG1vc3Qgb2YgdGhlIHBhcnRpY2lwYW50cyB3aGVyZSBlaXRoZXIgb3ZlciB3ZWlnaHQgb3Igb2Jlc2UuCgpgYGB7ciBjbGVhbmRhdGEsIHJlc3VsdHM9J2hpZGUnfQojIGdldCBkYXRhIGludG8gUgojc2V0d2QoIn4iKQojZ2V0d2QoKQoKbGlicmFyeShkcGx5cikKI2RkYXQgPC0gcmVhZC5jc3YoIi9Vc2Vycy9ta2F0dWFoZW5lL0Rlc2t0b3AvV0NVL1ItTWFjaGluZSBMZWFybmluZy9Bc3NpZ25tZW50L1dlZWsgMi9kaWFiZXRlc19iaW5hcnlfaGVhbHRoX2luZGljYXRvcnNfQlJGU1MyMDE1LmNzdiIsIHNraXA9MCkKZGRhdCA8LSByZWFkLmNzdigiaHR0cHM6Ly9tYXR1YWhlbmUuZ2l0aHViLmlvL1NUQTU1Mi9XZWVrJTIwMi9kaWFiZXRlc19iaW5hcnlfaGVhbHRoX2luZGljYXRvcnNfQlJGU1MyMDE1LmNzdiIsIHNraXA9MCkKCiNnZXR3ZCgpCiMgQ2F0ZWdvcml6ZSBpbmNvbWUgdmFyaWFibGUKZGRhdCRJbmNvbWVfY2F0IDwtIGN1dChkZGF0JEluY29tZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGMoLUluZiwgMywgNSwgNiwgSW5mKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkxvdyIsICJNZWRpdW0iLCAiSGlnaCIsICJWZXJ5IEhpZ2giKSkKCiN0YWJsZShkZGF0JEluY29tZSAsIGRkYXQkSW5jb21lX2NhdCApCgpkZGF0MiA8LWRkYXQKI2NvbFN1bXMoaXMubmEoZGRhdDIpKQoKCiMgYXNzaWduIG1lYW5pbmdmdWwgbGFiZWxzIHRvIEFnZQpkZGF0MiRBZ2UgPC0gZmFjdG9yKGRkYXQyJEFnZSwgCiAgbGV2ZWxzID0gMToxMywgCiAgbGFiZWxzID0gYygiMTgtMjQgeXJzIiwgIjI1LTI5IHlycyIsICIzMC0zNCB5cnMiLCAiMzUtMzkgeXJzIiwgIjQwLTQ0IHlycyIsIAogICAgICAgICAgICAgIjQ1LTQ5IHlycyIsICI1MC01NCB5cnMiLCAiNTUtNTkgeXJzIiwgIjYwLTY0IHlycyIsICI2NS02OSB5cnMiLCAKICAgICAgICAgICAgICI3MC03NCB5cnMiLCAiNzUtNzkgeXJzIiwgIjgwKyB5cnMiKSkKCgoKIyBCTUkgY2F0ZWdvcmllcwpkZGF0MiA8LSBkZGF0MiAlPiUKICBtdXRhdGUoQk1JX0NhdCA9IGN1dChCTUksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYygwLCAxOC41LCAyNC45LCAyOS45LCBJbmYpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIlVuZGVyd2VpZ2h0IiwgIk5vcm1hbCIsICJPdmVyd2VpZ2h0IiwgIk9iZXNlIikpKQoKCgojIFlFUy9OTyBsYWJlbHMKZGRhdDIgPC0gZGRhdDIgJT4lCiAgbXV0YXRlKAogICAgSGlnaENob2wgPSByZWNvZGUoSGlnaENob2wsICIwIiA9ICJObyIsICIxIiA9ICJZZXMiKSwKICAgIEhpZ2hCUCA9IHJlY29kZShIaWdoQlAsICIwIiA9ICJObyIsICIxIiA9ICJZZXMiKSwKICAgIFNtb2tlciA9IHJlY29kZShTbW9rZXIsICIwIiA9ICJObyIsICIxIiA9ICJZZXMiKSwKICAgIFN0cm9rZSA9IHJlY29kZShTdHJva2UsICIwIiA9ICJObyIsICIxIiA9ICJZZXMiKSwKICAgIEhlYXJ0RGlzZWFzZW9yQXR0YWNrID0gcmVjb2RlKEhlYXJ0RGlzZWFzZW9yQXR0YWNrLCAiMCIgPSAiTm8iLCAiMSIgPSAiWWVzIiksCiAgICBQaHlzQWN0aXZpdHkgPSByZWNvZGUoUGh5c0FjdGl2aXR5LCAiMCIgPSAiTm8iLCAiMSIgPSAiWWVzIiksCiAgICBGcnVpdHMgPSByZWNvZGUoRnJ1aXRzLCAiMCIgPSAiTm8iLCAiMSIgPSAiWWVzIiksCiAgICBWZWdnaWVzID0gcmVjb2RlKFZlZ2dpZXMsICIwIiA9ICJObyIsICIxIiA9ICJZZXMiKQogICkKCgojRGlhYmV0ZXMgc3RhdHVzLCBFZHVjYXRpb24gYW5kIEluY29tZSwgZXRjIGxhYmVscwpkZGF0MiA8LSBkZGF0MiAlPiUKICBtdXRhdGUoCiAgICBFZHVjYXRpb24gPSByZWNvZGUoRWR1Y2F0aW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAiMSIgPSAiTm8gSGlnaCBTY2hvb2wiLCAKICAgICAgICAgICAgICAgICAgICAgICAiMiIgPSAiU29tZSBIaWdoIFNjaG9vbCIsIAogICAgICAgICAgICAgICAgICAgICAgICIzIiA9ICJIaWdoIFNjaG9vbCBHcmFkdWF0ZSIsIAogICAgICAgICAgICAgICAgICAgICAgICI0IiA9ICJTb21lIENvbGxlZ2UiLCAKICAgICAgICAgICAgICAgICAgICAgICAiNSIgPSAiQ29sbGVnZSBHcmFkdWF0ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgIjYiID0gIkNvbGxlZ2UgNCB5ZWFycyBvciBtb3JlIChDb2xsZWdlIGdyYWR1YXRlKSIpLAogICAgSW5jb21lID0gcmVjb2RlKEluY29tZSwgCiAgICAgICAgICAgICAgICAgICAgIjEiID0gIjwkMTBLIiwgCiAgICAgICAgICAgICAgICAgICAgIjIiID0gIiQxMEstJDE1SyIsIAogICAgICAgICAgICAgICAgICAgICIzIiA9ICIkMTVLLSQyNUsiLCAKICAgICAgICAgICAgICAgICAgICAiNCIgPSAiJDI1Sy0kMzVLIiwgCiAgICAgICAgICAgICAgICAgICAgIjUiID0gIiQzNUstJDUwSyIsIAogICAgICAgICAgICAgICAgICAgICI2IiA9ICIkNTBLLSQ3NUsiLCAKICAgICAgICAgICAgICAgICAgICAiNyIgPSAiPiQ3NUsiLAogICAgICAgICAgICAgICAgICAgIC5kZWZhdWx0ID0gIlVua25vd24iKSwKICAgU2V4ID0gcmVjb2RlKFNleCwgCiAgICAgICAgICAgICAgICAgICIxIiA9ICJNYWxlIiwgCiAgICAgICAgICAgICAgICAgICIwIiA9ICJGZW1hbGUiLAogICAgICAgICAgICAgICAgLmRlZmF1bHQgPSAiVW5rbm93biIpLAogICBDaG9sQ2hlY2sgPSByZWNvZGUoQ2hvbENoZWNrLAogICAgICAgICAgICAgICAgICAgICAgIjEiID0gIlllcyIsCiAgICAgICAgICAgICAgICAgICAgICAiMCIgPSAiTm8iICksCiAgIAogICBEaWZmV2FsayA9IHJlY29kZShEaWZmV2FsaywKICAgICAgICAgICAgICAgICAgICAgICIxIiA9ICJZZXMiLAogICAgICAgICAgICAgICAgICAgICAgIjAiID0gIk5vIiApLAogIAogICBBbnlIZWFsdGhjYXJlID0gcmVjb2RlKEFueUhlYWx0aGNhcmUsCiAgICAgICAgICAgICAgICAgICAgICAiMSIgPSAiWWVzIiwKICAgICAgICAgICAgICAgICAgICAgICIwIiA9ICJObyIgKSwKCiAgIE5vRG9jYmNDb3N0ID0gcmVjb2RlKE5vRG9jYmNDb3N0LAogICAgICAgICAgICAgICAgICAgICAgIjEiID0gIlllcyIsCiAgICAgICAgICAgICAgICAgICAgICAiMCIgPSAiTm8iICksCiAgSHZ5QWxjb2hvbENvbnN1bXAgPSByZWNvZGUoSHZ5QWxjb2hvbENvbnN1bXAsCiAgICAgICAgICAgICAgICAgICAgICAiMSIgPSAiWWVzIiwKICAgICAgICAgICAgICAgICAgICAgICIwIiA9ICJObyIgKSwKICAgIERpYWJldGVzX2JpbmFyeSA9IHJlY29kZShEaWFiZXRlc19iaW5hcnksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIjAiID0gIk5vIERpYWJldGVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAiMSIgPSAiSGFzIERpYWJldGVzIiksCiAgCiAgR2VuSGx0aCA9IHJlY29kZShHZW5IbHRoLAogICAgICAgICAgICAgICAgICAiMSIgPSAiRXhjZWxsZW50IiwKICAgICAgICAgICAgICAgICAgICIyIiA9ICJWZXJ5IEdvb2QiLAogICAgICAgICAgICAgICAgICAgIjMiID0gIkdvb2QiLAogICAgICAgICAgICAgICAgICAgIjQiID0gIkZhaXIiLAogICAgICAgICAgICAgICAgICAgIjUiID0gIlBvb3IiLAogICAgICAgICAgICAgICAgICAgLmRlZmF1bHQgPSAiVW5rbm93biIpCiAgKQoKCgojdGFibGUgKGRkYXQyJEluY29tZSkKI3VuaXF1ZShkZGF0MiRJbmNvbWUpCgojIGNyZWF0ZSBzb21lIG1pc3NpbmcgZGF0YSBwb2ludHMgCiMgRGVmaW5lIHRoZSBwZXJjZW50YWdlIG9mIG1pc3NpbmcgdmFsdWVzIAptaXNzaW5nX3BlcmNlbnRhZ2UgPC0gMC4wNQoKIyBHZXQgdG90YWwgbnVtYmVyIG9mIHJvd3MKdG90YWxfcm93cyA8LSBucm93KGRkYXQyKQoKIyBBcHBseSBtaXNzaW5nIHZhbHVlcyB0byBhbGwgdmFyaWFibGVzCmRkYXQyIDwtIGRkYXQyICU+JQogIG11dGF0ZShhY3Jvc3MoZXZlcnl0aGluZygpLCB+IHsKICAgIG1pc3NfaWQgPC0gc2FtcGxlKDE6dG90YWxfcm93cywgc2l6ZSA9IHJvdW5kKG1pc3NpbmdfcGVyY2VudGFnZSAqIHRvdGFsX3Jvd3MpLCByZXBsYWNlID0gRkFMU0UpCiAgICAuW21pc3NfaWRdIDwtIE5BICAjIEFzc2lnbiBOQSB0byBzZWxlY3RlZCByb3dzCiAgICAuCiAgfSkpCgoKCgojIG92ZXJhbGwgc3VtbWFyeSBvZiB2YXJpYWJsZXMKbGlicmFyeShzdW1tYXJ5dG9vbHMpCmRmU3VtbWFyeShkZGF0MikKCiN0YWJsZShkZGF0MiRBZ2UpCiN0YWJsZShkZGF0MiRCTUlfQ2F0KQojc3VtbWFyeSAoZGRhdDIkQk1JKQpgYGAKCgoKYGBge3IgQk1JLCByZXN1bHRzPSdoaWRlJ30KIyBnZXQgZGF0YSBpbnRvIFIKI0JNSSB2YXJpYWJsZQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KGdyaWQpCmJtaTEgPC0gZ2dwbG90KGRkYXQyLCBhZXMoeCA9IEJNSSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIsIGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNykgKwogIGxhYnModGl0bGUgPSAiQk1JIERpc3RyaWJ1dGlvbiIsIHggPSAiQk1JIiwgeSA9ICJDb3VudCIpICsKICB0aGVtZV9taW5pbWFsKCkKCmJtaTIgPC0gZ2dwbG90KGRkYXQyLCBhZXMoeCA9IEJNSSkpICsKICBnZW9tX2RlbnNpdHkoZmlsbCA9ICJsaWdodGJsdWUiLCBhbHBoYSA9IDAuNikgKwogIGxhYnModGl0bGUgPSAiRGVuc2l0eSBQbG90IG9mIEJNSSIsIHggPSAiQk1JIiwgeSA9ICJEZW5zaXR5IikgKwogIHRoZW1lX21pbmltYWwoKQoKYm1pMyA8LSBnZ3Bsb3QoZGRhdDIsIGFlcyh5ID0gQk1JKSkgKwogIGdlb21fYm94cGxvdChmaWxsID0gInRvbWF0byIsIGFscGhhID0gMC43LCBvdXRsaWVyLmNvbG9yID0gInJlZCIpICsKICBsYWJzKHRpdGxlID0gIkJveHBsb3Qgb2YgQk1JIiwgeSA9ICJCTUkiKSArCiAgdGhlbWVfbWluaW1hbCgpCgpncmlkLmFycmFuZ2UoYm1pMSwgYm1pMiwgYm1pMywgbmNvbCA9IDIsIHRvcCA9IHRleHRHcm9iKCJPdmVydmlldyBvZiBCTUkiLCBncCA9IGdwYXIoZm9udHNpemUgPSAxNiwgZm9udGZhY2UgPSAiYm9sZCIpKSkgCgojY2hlY2sgc2tld25lc3Mgb2YgQk1JCmxpYnJhcnkoZTEwNzEpCnNrZXduZXNzKGRkYXQyJEJNSSwgbmEucm09VFJVRSkgCnNrZXduZXNzKGRkYXQyJEJNSSwgbmEucm09VFJVRSkgCgojIHJlbW92ZSBCTUkgb3V0bGllcnMKUTEgPC0gcXVhbnRpbGUoZGRhdDIkQk1JLCAwLjI1LCBuYS5ybSA9IFRSVUUpClEzIDwtIHF1YW50aWxlKGRkYXQyJEJNSSwgMC43NSwgbmEucm0gPSBUUlVFKQpJUVIgPC0gUTMgLSBRMQoKIyBEZWZpbmUgYWNjZXB0YWJsZSByYW5nZQpsb3dlcl9ib3VuZCA8LSBRMSAtIDEuNSAqIElRUgp1cHBlcl9ib3VuZCA8LSBRMyArIDEuNSAqIElRUgoKIyBSZW1vdmUgb3V0bGllcnMKZGRhdDMgPC0gZGRhdDJbZGRhdDIkQk1JID49IGxvd2VyX2JvdW5kICYgZGRhdDIkQk1JIDw9IHVwcGVyX2JvdW5kLCBdCgoKCiNwbG90IG9mIEJNSSB3aXRoIG91dGxpZXJzIHJlbW92ZWQ6IGRkYXQzIG5vdyBjb250YWlucyBkYXRhIHdpdGggbm8gb3V0bGllcnMKYm1pMTIgPC0gZ2dwbG90KGRkYXQzLCBhZXMoeCA9IEJNSSkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIsIGZpbGwgPSAic3RlZWxibHVlIiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNykgKwogIGxhYnModGl0bGUgPSAiQk1JIERpc3RyaWJ1dGlvbiIsIHggPSAiQk1JIiwgeSA9ICJDb3VudCIpICsKICB0aGVtZV9taW5pbWFsKCkKCmJtaTIyIDwtIGdncGxvdChkZGF0MywgYWVzKHggPSBCTUkpKSArCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAibGlnaHRibHVlIiwgYWxwaGEgPSAwLjYpICsKICBsYWJzKHRpdGxlID0gIkRlbnNpdHkgUGxvdCBvZiBCTUkiLCB4ID0gIkJNSSIsIHkgPSAiRGVuc2l0eSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmJtaTMyIDwtIGdncGxvdChkZGF0MywgYWVzKHkgPSBCTUkpKSArCiAgZ2VvbV9ib3hwbG90KGZpbGwgPSAidG9tYXRvIiwgYWxwaGEgPSAwLjcsIG91dGxpZXIuY29sb3IgPSAicmVkIikgKwogIGxhYnModGl0bGUgPSAiQm94cGxvdCBvZiBCTUkiLCB5ID0gIkJNSSIpICsKICB0aGVtZV9taW5pbWFsKCkKCmdyaWQuYXJyYW5nZShibWkxMiwgYm1pMjIsIGJtaTMyLCBuY29sID0gMiwgdG9wID0gdGV4dEdyb2IoIk92ZXJ2aWV3IG9mIEJNSSB3aXRoIG5vIG91dGxpZXJzIiwgZ3AgPSBncGFyKGZvbnRzaXplID0gMTYsIGZvbnRmYWNlID0gImJvbGQiKSkpIAoKCiNjYXRlZ29yaXplZCBCTUkgYmFyIGNoYXJ0CmJtaWdycDwtIGdncGxvdChkZGF0MyAlPiUgZmlsdGVyKCFpcy5uYShCTUlfQ2F0KSksIGFlcyh4ID0gQk1JX0NhdCkpICsKICBnZW9tX2JhcihmaWxsID0gImxpZ2h0Ymx1ZSIgLCB3aWR0aCA9IDAuNikgKwogIGxhYnModGl0bGUgPSAiQk1JIENhdGVnb3JpZXMgRGlzdHJpYnV0aW9uIiwKICAgICAgIHggPSAiQk1JIGNhdGVnb3J5IiwKICAgICAgIHkgPSAiQ291bnQiCiAgICAgICApICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKHBsb3QubWFyZ2luID0gbWFyZ2luKDIsIDIsIDIsIDIpICkKICAKYm1pZ3JwCmBgYAoKICArIERpYWJldGVzIFN0YXR1czogSW4gdGhlIHNhbXBsZSwgbWFqb3JpdHkgb2YgdGhlIHBhcnRpY2lwYW50cyBkaWQgbm90IGhhdmUgZGlhYmV0ZXMoODYlKS4gT25seSBhIHNtYWxsZXIgcHJvcG9ydGlvbiB3aGVyZSBkaWFiZXRpYyBvciBoYWQgcHJlLWRpYWJldGVzLiBUaGlzIHN1Z2dlc3RzIGxvdyBwcmV2YWxlbmNlIG9mIGRpYWJldGVzIGluIG91ciBzYW1wbGUuIAogICsgTWVudGFsIEhlYWx0aDogSGlzdG9ncmFtIGFuZCBkZW5zaXR5IHBsb3RzIHNob3dlZCBmZXcgcGVvcGxlIGhhZCBmZXcgZGF5cyB3aXRoIHBvb3IgbWVudGFsIGhlYWx0aCB0aGUgbGFzdCAzMCBkYXlzIChtZWFuID0gYXBwcm94aW1hdGVseSAzIGRheXMgb2YgYmFkIG1lbnRhbCBoZWFsdGggZGF5cykuCiAgICBPdXRsaWVycyB3ZXJlIHJlcGxhY2VkIHdpdGggbWVhbiB2YWx1ZXMuCiAgKyBQaHlzaWNhbCBIZWFsdGggaW4gbGFzdCAzMCBkYXlzIGRpc3RyaWJ1dGlvbiBzaG93ZWQgb3V0bGllcnMgYW5kIHRoZXNlIHZhbHVlcyB3ZXJlIHJlcGxhY2VkIHdpdGggdGhlIG1lYW4uCiAgKyBHZW5lcmFsIEhlYWx0aCBTdGF0dXM6IE1vc3QgcGVvcGxlIHJlcG9ydGVkIHZlcnkgZ29vZCBvciBnb29kIGhlYWx0aCBzdGF0dXMgb3ZlcmFsbCB3aXRoIHNrZXduZXNzIG9ic2VydmVkIHRvd2FyZHMgcG9vciBoZWFsdGguIAogICAgYW5kIHNvIG5vIHNwZWNpYWwgY2hhbmdlcyB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIHZhcmlhYmxlLiAKICArIEluY29tZSB2YXJpYWJsZSB3YXMgbmVnYXRpdmVseSBza2V3ZWQuIE1vc3QgcGFydGljaXBhbnRzIGVhcm5lZCBoaWdoZXIgaW5jb21lLiBUaGUgdmFyaWFibGUgaXMgY2F0ZWdvcml6ZWQgaW50byBMb3csIE1lZGl1bSwgYW5kIEhpZ2ggaW5jb21lIGxldmVscy4KICArIFNleDogTW9yZSBmZW1hbGVzIHBhcnRpY2lwYXRlZCBpbiB0aGUgc2FtcGxlIGRhdGEgdGhhbiBtYWxlcy4gCiAgKyBBZ2U6IERpc3RyaWJ1dGlvbiBvZiBhZ2Ugd2FzIHN1Y2ggdGhhdCBtYWpvcml0eSBvZiBwYXJ0aWNpcGFudHMgd2VyZSBiZXlvbmQgNDAgeWVhcnMgb2xkLiBUaGlzIHN1Z2dlc3RzIHRoYXQgbW9zdCBwYXJ0aWNpcGFudHMgd2VyZSBvbGRlciBhbmQgYWdlIHNob3VsZCAgICAgY29udHJvbGxlZCBmb3IgaW4gYW55IGFuYWx5c2lzLgogICsgRWR1Y2F0aW9uOiBNb3N0IG9mIHRoZSBwYXJ0aWNpcGFudHMgaGFkIGEgaGlnaCBzY2hvb2wgZGlwbG9tYSBvciBoaWdoZXIgKG92ZXIgODAlKS4gCiAgKyBIaWdoIGJsb29kIFByZXNzdXJlIGFuZCBIaWdoIENob2xlc3Rlcm9sOiBNb3JlIHBhcnRpY2lwYW50cyBkaWQgbm90IGhhdmUgaGlnaCBibG9vZCBwcmVzc3VyZSBhbmQgbW9yZSBkaWQgbm90IGhhdmUgYW55IGNob2xlc3Rlcm9sIGNoZWNrcyBpbiB0aGUgbGFzdCA1IHllYXJzLiAKICArIFNtb2tlcjogQWJvdXQgNDQlIG9mIHRoZSBwYXJ0aWNpcGFudHMgc21va2VkIGF0IGxlYXN0IDEwMCBjaWdhcmV0dGVzIGluIHRoZWlyIGVudGlyZSBsaWZldGltZS4gQ29uc2lkZXJpbmcgaG93IHNtb2tpbmcgYWZmZWN0cyBvdXIgaGVhbHRoIGFuZCB3aXRoIHN1Y2ggbWFueSBpbiAgICAgc2FtcGxlLCBjb250cm9sbGluZyBmb3IgdGhpcyB2YXJpYWJsZSBpbiBvdXIgYW5hbHlzaXMgYW5kIGV4cGxvcmluZyBob3cgdGhpcyB2YXJpYWJsZSBpbnRlcmFjdHMgd2l0aCBvdGhlcnMgdG8gaW1wYWN0IGRpYWJldGVzIHdpbGwgYmUgc3R1ZGllZC4KICArIEhlYXZ5IEFsY29ob2wgY29uc3VtcHRpb24gLSBib3RoIG1lbiBhbmQgd29tZW4gcmVwb3J0ZWQgdGhleSBhcmUgbm90IGhlYXZ5IGRyaW5rZXJzIGJ1dCB0aGVzZSBjb3VsZCBiZSBpbmNvcnJlY3QgcmVwcmVzZW50YXRpb24gZHVlIHRvIHRoZSBmYWN0IHRoYXQgdGhleSBtYXkgcmVwb3J0IGFzIG5vdCBoZWF2eSBkcmlua2VycyBmb3Igc29jaWFsbHkgZGVzaXJhYmxlIHJlc3BvbnNlcyBhbmQgZXhwZWN0YXRpb25zLiBUaGUgYW5hbHlzaXMgY2FuIGJlIGNvbmR1Y3RlZCBmb3IgbWVuIGFuZCB3b21lbiBzZXBhcmF0ZWx5IGFuZCBmb3IgdGhvc2Ugd2hvIHJlcG9ydGVkIGFzIGhlYXZ5IGRyaW5rZXJzIHRvIHVuY292ZXIgaGlkZGVuIHJlbGF0aW9ucy4gCiAgKyBIZWFydCBkaXNlYXNlL2F0dGFjayB3YXMgbm90IHByZXZhbGVudCBpbiBvdXIgc2FtcGxlLiBCdXQgd2Uga25vdyB0aGF0IGRpYWJldGVzIGltcGFjdHMgdGhlIGhlYXJ0IGZ1bmN0aW9uLCBpdCB3aWxsIGJlIGludGVyZXN0aW5nIHRvIHNlZSBpZiB0aG9zZSB3aG8gaGFkIGRpYWJldGVzIHJlcG9ydGVkIHRvIGF2ZSBoYWQgYW55IG9mIHRoZXNlIGNvbmRpdGlvbnMuIAogICsgU3Ryb2tlOiBNb3N0IHBlb3BsZSBoYWQgbmV2ZXIgYmVlbiB0b2xkIHRoZXkgaGFkIGRpYWJldGVzICg5NSUpLiAKICArIE90aGVyIHZhcmlhYmxlczogTW9zdCBwZW9wbGUgZGlkIG5vdCBoYXZlIGRpZmZpY3VsdHkgd2Fsa2luZyB1cCB0aGUgc3RhaXJzLCB3ZXJlIHBoeXNpY2FsbHkgYWN0aXZlIGluIHRoZSBwYXN0IDMwIGRheXMsIGhhZCBzb21lIGZvcm0gb2YgaGVhbHRoIGluc3VyYW5jZSBhbmQgY291bGQgc2VlIGEgZG9jdG9yIHdoZW4gbmVlZGVkLCBjb25zdW1lZCB2ZWdldGFibGVzIG9uY2Ugb3IgbW9yZSB0aW1lcyBhIGRheSwgYnV0IHNsaWdodGx5IG1vcmUgZGlkIG5vdCBjb25zdW1lIGZydWl0cyBhdCB0aGUgc2FtZSByYXRlIGFzIHZlZ2V0YWJsZXMuCgpgYGB7ciBNZW5ILCByZXN1bHRzPSdoaWRlJ30KIyBEaWFiZXRlcyBTdGF0dXMKZ2dwbG90KGRkYXQzICU+JSBmaWx0ZXIoIWlzLm5hKERpYWJldGVzX2JpbmFyeSkpLCBhZXMoeCA9IGZhY3RvcihEaWFiZXRlc19iaW5hcnkpKSkgKwogIGdlb21fYmFyKGZpbGwgPSAibGlnaHRibHVlIiAsIHdpZHRoID0gMC40KSArCiAgbGFicyh0aXRsZSA9ICJEaWFiZXRlcyBTdGF0dXMiLAogICAgICAgeCA9ICJEaWFiZXRlcyBTdGF0dXMiLAogICAgICAgeSA9ICJDb3VudCIKICAgICAgICkgKwogIHRoZW1lX2NsYXNzaWMoKSsKICB0aGVtZShwbG90Lm1hcmdpbiA9IG1hcmdpbigyLCAyLCAyLCAyKSApCgojUGVyY2VudGFnZXMgd2l0aGluIGRpYWJldGVzCkRpYWIucGVyY2VudGFnZXMgPC0gZGRhdDMgJT4lCiAgY291bnQoRGlhYmV0ZXNfYmluYXJ5KSAlPiUKICBtdXRhdGUoUGVyY2VudGFnZSA9IG4gLyBzdW0obikgKiAxMDApCkRpYWIucGVyY2VudGFnZXMKCiNNZW50YWwgSGVhbHRoIFZhcmlhYmxlcwpzdW1tYXJ5KGRkYXQzJE1lbnRIbHRoKQptZW5oMSA8LSBnZ3Bsb3QoZGRhdDIsIGFlcyh4ID0gTWVudEhsdGgpKSArCiAgZ2VvbV9kZW5zaXR5KGZpbGwgPSAieWVsbG93IiwgYWxwaGEgPSAwLjYpICsKICBsYWJzKHRpdGxlID0gIkRlbnNpdHkgUGxvdCBvZiBub3QgZ29vZCBtZW50YWwgaGVhbHRoIGRheXMiLCB4ID0gIk1lbnRhbCBIZWFsdGgiLCB5ID0gIkRlbnNpdHkiKSArCiAgdGhlbWVfbWluaW1hbCgpCgoKbWVuaDIgIDwtIGdncGxvdChkZGF0MywgYWVzKHggPSBNZW50SGx0aCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW53aWR0aCA9IDIsIGZpbGwgPSAieWVsbG93IiwgY29sb3IgPSAiYmxhY2siLCBhbHBoYSA9IDAuNykgKwogIGxhYnModGl0bGUgPSAiSGlzdG9ncmFtIG9mIG5vdCBnb29kIG1lbnRhbCBoZWFsdGggZGF5cyIsIHggPSAiRGF5cyIsIHkgPSAiQ291bnQiKSArCiAgdGhlbWVfbWluaW1hbCgpCgoKbWVuaDMgPC0gZ2dwbG90KGRkYXQzLCBhZXMoeSA9IE1lbnRIbHRoKSkgKwogIGdlb21fYm94cGxvdChmaWxsID0gInllbGxvdyIsIGFscGhhID0gMC43LCBvdXRsaWVyLmNvbG9yID0gInJlZCIpICsKICBsYWJzKHRpdGxlID0gIkJveHBsb3Qgb2YgTnVtYmVyIG9mIGRheXMgTWVudGFsIGhlYWx0aCB3YXMgbm90IGdvb2QiLCB5ID0gIk1lbnRhbCBIZWFsdGggRGF5cyIpICsKICB0aGVtZV9taW5pbWFsKCkKCgpncmlkLmFycmFuZ2UobWVuaDEsIG1lbmgyLCBtZW5oMywgbmNvbCA9IDIsIHRvcCA9IHRleHRHcm9iKCJPdmVydmlldyBvZiBNZW50YWwgSGVhbHRoIGluIFBhc3QgMzAgRGF5cyIsIGdwID0gZ3Bhcihmb250c2l6ZSA9IDE2LCBmb250ZmFjZSA9ICJib2xkIikpKSAKCiMgRGVmaW5lIGEgZnVuY3Rpb24gdG8gcmVwbGFjZSBvdXRsaWVycyB3aXRoIHRoZSBtZWFuCnJlcGxhY2Vfb3V0bGllcnNfd2l0aF9tZWFuIDwtIGZ1bmN0aW9uKHgpIHsKICBRMSA8LSBxdWFudGlsZSh4LCAwLjI1LCBuYS5ybSA9IFRSVUUpCiAgUTMgPC0gcXVhbnRpbGUoeCwgMC43NSwgbmEucm0gPSBUUlVFKQogIElRUiA8LSBRMyAtIFExCiAgCiAgIyBEZWZpbmUgbG93ZXIgYW5kIHVwcGVyIGJvdW5kcwogIGxvd2VyX2JvdW5kIDwtIFExIC0gMS41ICogSVFSCiAgdXBwZXJfYm91bmQgPC0gUTMgKyAxLjUgKiBJUVIKICAKICAjIFJlcGxhY2Ugb3V0bGllcnMgd2l0aCB0aGUgbWVhbgogIHhbeCA8IGxvd2VyX2JvdW5kIHwgeCA+IHVwcGVyX2JvdW5kXSA8LSBtZWFuKHgsIG5hLnJtID0gVFJVRSkKICAKICByZXR1cm4oeCkKfQoKIyBBcHBseSB0aGUgZnVuY3Rpb24gdG8gbWVudGFsIGhlYWx0aCB0byByZXBsYWNlIG91dGxpZXJzIHdpdGggbWVhbiB2YWx1ZQpkZGF0MyRNZW50SGx0aCA8LSByZXBsYWNlX291dGxpZXJzX3dpdGhfbWVhbihkZGF0MyRNZW50SGx0aCkKCiNQaHlzaWNhbCBIZWFsdGggaGlzdG9ncmFtClBoICA8LSBnZ3Bsb3QoZGRhdDMsIGFlcyh4ID0gUGh5c0hsdGgpKSArCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAyLCBmaWxsID0gInN0ZWVsYmx1ZSIsIGNvbG9yID0gImJsYWNrIiwgYWxwaGEgPSAwLjcpICsKICBsYWJzKHRpdGxlID0gIlBoeXNpY2FsIEhlYWx0aCBEYXlzIiwgeCA9ICJEYXlzIiwgeSA9ICJDb3VudCIpICsKICB0aGVtZV9taW5pbWFsKCkKI1BoCgojIEFwcGx5IHRoZSBmdW5jdGlvbiB0byBtZW50YWwgaGVhbHRoIHRvIHJlcGxhY2Ugb3V0bGllcnMgd2l0aCBtZWFuIHZhbHVlCmRkYXQzJFBoeXNIbHRoIDwtIHJlcGxhY2Vfb3V0bGllcnNfd2l0aF9tZWFuKGRkYXQzJFBoeXNIbHRoKQoKI2NhdGVnb3JpemVkIEdlbmVyYWwgSGVhbHRoIGJhciBjaGFydApkZGF0MyA8LSBkZGF0MyAlPiUKICBtdXRhdGUoR2VuSGx0aCA9IGZhY3RvcihHZW5IbHRoLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHMgPSBjKCJQb29yIiwgIkZhaXIiLCAiR29vZCIsICJWZXJ5IEdvb2QiLCAiRXhjZWxsZW50IiksIAogICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWQgPSBUUlVFKSkgIApHaCA8LSBnZ3Bsb3QoZGRhdDMgJT4lIGZpbHRlcighaXMubmEoR2VuSGx0aCkpLCBhZXMoeCA9IEdlbkhsdGgpKSArCiAgZ2VvbV9iYXIoZmlsbCA9ICJibHVlIiwgd2lkdGggPTAuNCkgKwogIGxhYnModGl0bGUgPSAiR2VuZXJhbCBIZWFsdGggU3RhdHVzIiwKICAgICAgIHggPSAiR2VuZXJhbCBIZWFsdGgiLAogICAgICAgeSA9ICJDb3VudCIKICAgICAgICkgKwogIHNjYWxlX3hfZGlzY3JldGUoZXhwYW5kID0gYygwLjEsIDAuMSkpKwogIHRoZW1lX2NsYXNzaWMoKQpHaAoKCiNjYXRlZ29yaXplZCBTZXggY2hhcnQKU2V4IDwtIGdncGxvdChkZGF0MyAlPiUgZmlsdGVyKCFpcy5uYShTZXgpKSwgYWVzKHggPSBTZXgpKSArCiAgZ2VvbV9iYXIoZmlsbCA9ICJibHVlIikgKwogIGxhYnModGl0bGUgPSAiR2VuZGVyIiwKICAgICAgIHggPSAiR2VuZGVyIiwKICAgICAgIHkgPSAiQ291bnQiCiAgICAgICApICsKICB0aGVtZV9jbGFzc2ljKCkKI1NleAp1bmlxdWUoZGRhdDMkU2V4KTsKCiMgQWdlIEdyb3VwcwpBZ2UgPC0gZ2dwbG90KGRkYXQyICU+JSBmaWx0ZXIoIWlzLm5hKEFnZSkpLCBhZXMoeCA9IEFnZSkpICsKICBnZW9tX2JhcihmaWxsID0gImJsdWUiKSArCiAgbGFicyh0aXRsZSA9ICJBZ2UgZ3JvdXAgQmFyIENoYXJ0IiwKICAgICAgIHggPSAiQWdlIEdyb3VwIiwKICAgICAgIHkgPSAiQ291bnQiCiAgICAgICApICsKICB0aGVtZV9jbGFzc2ljKCkKI0FnZQoKQWdlLnBlcmNlbnRhZ2VzIDwtIGRkYXQgJT4lCiAgY291bnQoQWdlKSAlPiUKICBtdXRhdGUoUGVyY2VudGFnZSA9IG4gLyBzdW0obikgKiAxMDApCkFnZS5wZXJjZW50YWdlcwoKIyBFZHVjYXRpb24KRWR1LnBlcmNlbnRhZ2VzIDwtIGRkYXQgJT4lCiAgY291bnQoRWR1Y2F0aW9uKSAlPiUKICBtdXRhdGUoUGVyY2VudGFnZSA9IG4gLyBzdW0obikgKiAxMDApCkVkdS5wZXJjZW50YWdlcwoKIyBTbW9rZXIKU21va2UucGVyY2VudGFnZXMgPC0gZGRhdCAlPiUKICBjb3VudChTbW9rZXIpICU+JQogIG11dGF0ZShQZXJjZW50YWdlID0gbiAvIHN1bShuKSAqIDEwMCkKU21va2UucGVyY2VudGFnZXMKCiMgU3Ryb2tlClN0cm9rZS5wZXJjZW50YWdlcyA8LSBkZGF0ICU+JQogIGNvdW50KFN0cm9rZSkgJT4lCiAgbXV0YXRlKFBlcmNlbnRhZ2UgPSBuIC8gc3VtKG4pICogMTAwKQpTdHJva2UucGVyY2VudGFnZXMKCmBgYAoKClwKCiMjIDQuIFJlbGF0aW9uc2hpcCBiZXR3ZWVuIEZlYXR1cmVzIC0gQml2YXJpYXRlCgpcCldlIHdpbGwgbm93IGV4cGxvcmUgYW5kIGhhdmUgdmlzdWFsaXphdGlvbnMgb2YgcmVsYXRpb25zaGlwcyBhbW9uZyBzZXZlcmFsIHZhcmlhYmxlcyBpbiBvdXIgc2FtcGxlIGRhdGEuIFdlIHdpbGwgYmUgbG9va2luZyBhdCB2aXN1YWxzIGZvciB0d28gb3IgbW9yZSBudW1lcmljYWwgZmVhdHVyZSB2YXJpYWJsZXMsIGNhdGVnb3JpY2FsIHZhcmlhYmxlcyBhbmQgdmlzdWFscyB0aGF0IGxvb2sgY29tYmluYXRpb25zIG9mIHRoZXNlIHRvIGFpZCBpbiBvdXIgdW5kZXJzdGFuZGluZyBvZiB0aGUgZGF0YSBhbmQgaG93IGl0IGluZmx1ZW5jZXMgb3VyIHVuZGVyc3RhbmRpbmcgb2YgaG93IHRvIGFwcHJvYWNoIGFuYWx5c2lzIG9mIHRoZSBkYXRhLiAKCiAgKyBEaWFiZXRlcyBhbmQgQk1JIHBsb3RzIDogVGhlIGJveCBwbG90IHNob3dpbmcgdGhlIGRpYWJldGVzIGFuZCBCTUkgcGxvdCBzaG93cyB0aGUgbWVkaWFuIEJNSSBpbiB0aGUgZGlhYmV0aWMgZ3JvdXAgaXMgaGlnaGVyIHN1Z2dlc3RzIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIAogICAgdGhlc2UgMiB2YXJpYWJsZXMuIEFkZGl0aW9uYWxseSwgdGhlIGRlbnNpdHkgcGxvdCBzaG93cyBoaWdoZXIgQk1JIGluIHRoZSBkaWFiZXRpYyBncm91cCB0aGFuIHRoZSBub24tZGlhYmV0aWMgZ3JvdXAuCiAgKyBEaWFiZXRlcyBhbmQgUGh5c2ljYWwgQWN0aXZpdHkgcGxvdDogVGhlIGJpdmFyaWF0ZSBwbG90IHNob3dzIHRoYXQgd2hpbGUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBwaHlzaWNhbCBhY3Rpdml0eSBpbiB0aGUgcGFzdCAzMCBkYXlzIGlzIHNpbWlsYXIsIGZhciBsZXNzICAgICAgICAKICAgIGRpYWJldGljIHBlb3BsZSB3ZXJlIHBoeXNpY2FsbHkgYWN0aXZlIGluIHRoZSBsYXN0IDMwIGRheXMuCgoKCgpgYGB7ciB0d292YXIsIHJlc3VsdHM9J2hpZGUnfQojIyMjIyMjIyMjIHR3byB2YXJpYWJsZSByZWxhdGlvbnNoaXBzCgojIGRpYWJldGVzIGFuZCBCTUkKIApnZ3Bsb3QoZGRhdDMlPiUgZmlsdGVyKCFpcy5uYShEaWFiZXRlc19iaW5hcnkpKSwgYWVzKHggPSBmYWN0b3IoRGlhYmV0ZXNfYmluYXJ5KSwgeSA9IEJNSSwgZmlsbCA9IGZhY3RvcihEaWFiZXRlc19iaW5hcnkpKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBsYWJzKHRpdGxlID0gIkJNSSBEaXN0cmlidXRpb24gYnkgRGlhYmV0ZXMgU3RhdHVzIiwKICAgICAgIHggPSAiRGlhYmV0ZXMgU3RhdHVzIiwKICAgICAgIHkgPSAiQk1JIikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsICJncmVlbiIpKSArCiAgdGhlbWVfY2xhc3NpYygpKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCmdncGxvdChkZGF0MyU+JSBmaWx0ZXIoIWlzLm5hKERpYWJldGVzX2JpbmFyeSkpLCBhZXMoeCA9IEJNSSwgZmlsbCA9IGZhY3RvcihEaWFiZXRlc19iaW5hcnkpKSkgKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuNSkgKwogIGxhYnModGl0bGUgPSAiQk1JIERlbnNpdHkgUGxvdCBieSBEaWFiZXRlcyBTdGF0dXMiLAogICAgICAgeCA9ICJCTUkiLAogICAgICAgeSA9ICJEZW5zaXR5IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsICJncmVlbiIpKSArCiAgdGhlbWVfbWluaW1hbCgpKwogIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCgoKI2RpYWJldGVzIGFuZCBwaHlzaWNhbCBoZWFsdGgKCmdncGxvdChkZGF0MyU+JSBmaWx0ZXIoIWlzLm5hKERpYWJldGVzX2JpbmFyeSkgJiAhaXMubmEoUGh5c0FjdGl2aXR5KSksIGFlcyh4ID0gZmFjdG9yKERpYWJldGVzX2JpbmFyeSksIGZpbGwgPSBmYWN0b3IoUGh5c0FjdGl2aXR5KSkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIpICsKICBsYWJzKHRpdGxlID0gIkdyb3VwZWQgQmFyIFBsb3Qgb2YgRGlhYmV0ZXMgU3RhdHVzIGFuZCBQaHlzaWNhbCBBY3Rpdml0eSBpbiBwYXMgMzAgZGF5cyIsCiAgICAgICB4ID0gIkRpYWJldGVzIFN0YXR1cyIsCiAgICAgICB5ID0gIkNvdW50IikgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImJsdWUiLCAicmVkIiwgImdyZWVuIikpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZCh0aXRsZSA9ICJQeXNpY2FsbHkgQWN0aXZlIGxhc3QgMzAgZGF5cyIpKSArCiAgdGhlbWVfY2xhc3NpYygpCiAgCgojY29sbmFtZXMoZGRhdDMpCgpgYGAKCgoKYGBge3IgbXVsdGl2YXJ9CiNjb3JyZWxhdGlvbiBwbG90IG9mIG51bWVyaWNhbCB2YXJpYWJsZXMKbGlicmFyeShnZ2NvcnJwbG90KQpzZWxlY3RfdmFycyA8LSBjKCJQaHlzSGx0aCIsICJNZW50SGx0aCIsICJHZW5IbHRoIiwgIkJNSSIpCmNvcnJfbWF0cml4IDwtIGNvcihkZGF0ICU+JSBzZWxlY3QoYWxsX29mKHNlbGVjdF92YXJzKSksIHVzZSA9ICJjb21wbGV0ZS5vYnMiKQoKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KHJlc2hhcGUyKQoKIyBDb252ZXJ0IG1hdHJpeCB0byBsb25nIGZvcm1hdApjb3JyX21lbHQgPC0gbWVsdChjb3JyX21hdHJpeCkKCiMgUGxvdCBoZWF0bWFwCiMgUGxvdCB3aXRoIHRleHQgbGFiZWxzCmNvcjEgPC0gZ2dwbG90KGNvcnJfbWVsdCwgYWVzKHggPSBWYXIxLCB5ID0gVmFyMiwgZmlsbCA9IHZhbHVlKSkgKwogIGdlb21fdGlsZSgpICsKICBnZW9tX3RleHQoYWVzKGxhYmVsID0gcm91bmQodmFsdWUsIDIpKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gNCkgKyAgIyBBZGQgdmFsdWVzCiAgc2NhbGVfZmlsbF9ncmFkaWVudDIobG93ID0gImJsdWUiLCBtaWQgPSAid2hpdGUiLCBoaWdoID0gInJlZCIsIG1pZHBvaW50ID0gMCkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicyh0aXRsZSA9ICJDb3JyZWxhdGlvbiBIZWF0bWFwIiwgZmlsbCA9ICJDb3JyZWxhdGlvbiIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQoKI2luc3RhbGwucGFja2FnZXMoImNvcnJwbG90IikKbGlicmFyeShjb3JycGxvdCkKCmNvcnJwbG90KGNvcnJfbWF0cml4LCBtZXRob2QgPSAiY29sb3IiLCB0eXBlID0gInVwcGVyIiwKICAgICAgICAgY29sID0gY29sb3JSYW1wUGFsZXR0ZShjKCJibHVlIiwgIndoaXRlIiwgInJlZCIpKSgyMDApLAogICAgICAgICB0bC5jZXggPSAwLjcsIHRsLmNvbCA9ICJibGFjayIsCiAgICAgICAgIGFkZENvZWYuY29sID0gImJsYWNrIiwgbnVtYmVyLmNleCA9IDAuOCkgICMgQWRkIHZhbHVlcwoKCiNpbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkocGxvdGx5KQp1bmlxdWUoZGRhdDMkSW5jb21lX2NhdCkKbXljb2xvcnMgPC0gYygiTG93IiA9ICJyZWQiLCAiTWVkaXVtIiA9ICJvcmFuZ2UiLCAiSGlnaCIgPSAiZ3JlZW4iLCAiVmVyeSBIaWdoIiA9ICJibHVlIikKCmdncGxvdGx5X2RlbnNpdHkgPC0gZGRhdDMlPiUgZmlsdGVyKCFpcy5uYShJbmNvbWVfY2F0KSAmICFpcy5uYShEaWFiZXRlc19iaW5hcnkpKSAgJT4lIAogIGdncGxvdChhZXMoeCA9IEJNSSwgY29sb3IgPSBJbmNvbWVfY2F0LCBmaWxsID0gSW5jb21lX2NhdCkpICsKICBnZW9tX2RlbnNpdHkobGluZXdpZHRoID0gMC43NSwgYWxwaGEgPSAwLjYpICsKICB4bGFiKCJCTUkgSW5kZXgiKSArIAogIGxhYnMoY29sb3IgPSAiSW5jb21lIEdyb3VwcyIsIGZpbGwgPSAiSW5jb21lIEdyb3VwcyIpICsKICBnZ3RpdGxlKCJEZW5zaXR5IEN1cnZlIG9mIEJNSSBhY3Jvc3MgSW5jb21lIEdyb3VwcyIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXljb2xvcnMpICsgICMgQ3VzdG9tIGxpbmUgY29sb3JzCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gbXljb2xvcnMpICsgICMgQ3VzdG9tIGZpbGwgY29sb3JzCiAgICAgICAgICAgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KGMoMiwxLDIsMSksICJjbSIpLAogICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICArIAogIGZhY2V0X3dyYXAofiBEaWFiZXRlc19iaW5hcnkpICAjIFNwbGl0IGJ5IGRpYWJldGVzIHN0YXR1cwoKZ2dwbG90bHkoZ2dwbG90bHlfZGVuc2l0eSkKCgoKbXljb2xvcnMubiA8LSBjKCJQb29yIiA9ICJyZWQiLCAiRmFpciIgPSAib3JhbmdlIiwgIkdvb2QiID0gImdyZWVuIiwgIlZlcnkgR29vZCIgPSAiYmx1ZSIsICJFeGNlbGxlbnQiID0gImxpZ2h0Ymx1ZSIpCmdncGxvdGx5X2RlbnNpdHkubiA8LSBkZGF0MyU+JSBmaWx0ZXIoIWlzLm5hKEdlbkhsdGgpICYgIWlzLm5hKERpYWJldGVzX2JpbmFyeSkpICAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gQk1JLCBjb2xvciA9IEdlbkhsdGgsIGZpbGwgPSBHZW5IbHRoKSkgKwogIGdlb21fZGVuc2l0eShsaW5ld2lkdGggPSAwLjc1LCBhbHBoYSA9IDAuNikgKwogIHhsYWIoIkJNSSBJbmRleCIpICsgCiAgbGFicyhjb2xvciA9ICJHZW5lcmFsIEhlYWx0aCIsIGZpbGwgPSAiR2VuZXJhbCBIZWFsdGgiKSArCiAgZ2d0aXRsZSgiRGVuc2l0eSBDdXJ2ZSBvZiBCTUkgYWNyb3NzIEdlbmVyYWwgSGVhbHRoIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteWNvbG9ycy5uKSArICAjIEN1c3RvbSBsaW5lIGNvbG9ycwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IG15Y29sb3JzLm4pICsgICMgQ3VzdG9tIGZpbGwgY29sb3JzCiAgICAgICAgICAgdGhlbWUocGxvdC5tYXJnaW4gPSB1bml0KGMoMiwxLDIsMSksICJjbSIpLAogICAgICAgICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpICArIAogIGZhY2V0X3dyYXAofiBEaWFiZXRlc19iaW5hcnkpICAjIFNwbGl0IGJ5IGRpYWJldGVzIHN0YXR1cwoKZ2dwbG90bHkoZ2dwbG90bHlfZGVuc2l0eS5uKQoKCgpgYGAKCgpcCgojIyA1LiBSZWxhdGlvbnNoaXAgYmV0d2VlbiBGZWF0dXJlcyAtIE11dGxpdmFyaWF0ZSAKClwKVGhlIGRlbnNpdHkgcGxvdCBvZiBCTUkgYW5kIEluY29tZSBncm91cHMgc2hvd3MgdGhhdCBCTUkgaXMgaGlnaGVzdCBpbiBtb3JlIHBhcnRpY2lwYW50cyBpbiB0aGUgbG93IGFuZCBtZWRpdW0gaW5jb21lIGdyb3Vwcy4gQW5kIHBhcnRpY2lwYW50cyBpbiB0aGUgdmVyeSBoaWdoIGluY29tZSBncm91cCBhcmUgYW1vbmcgdGhvc2Ugd2l0aCBCTUkgbGVzcyB0aGFuIDMwIG9yIGhlYWx0aGllci4gV2hlbiB0aGUgcGxvdCBpcyBzcGxpdCBieSBkaWFiZXRlcyBzdGF0dXMsIHdlIG9ic2VydmVkIHNpbWlsYXIgZGlzdHJpYnV0aW9uIGJ1dCB3ZSBzZWUgdGhhdCB2YXJpYW5jZSBpbiB0aGUgaW5jb21lIGdyb3VwcyBpcyBub3QgYXMgZGlzdGluY3QgZm9yIGhpZ2ggYW5kIHZlcnkgaGlnaCBncm91cHMuIFdoaWxlIGhpZ2hlciBCTUkgaXMgY29tb24gaW4gYWxsIGRpYWJldGljcywgaXQgaXMgbW9yZSBjb21tb24gaW4gdGhlIExvdyBhbmQgTWVkaXVtIGluY29tZSBncm91cHMgYW5kIGluZGljYXRlcyBzb21lIHZhcmlhYmlsaXR5IGluIHRoZSB0aGUgZGlhYmV0aWMgZ3JvdXAuIFNpbWlsYXIgcGF0dGVybnMgd2VyZSBvYnNlcnZlZCBhbW9uZyBnZW5lcmFsIGhlYWx0aCBzdGF0dXMgd2l0aCB0aG9zZSBpbiB0aGUgcG9vciBoZWFsdGggc3RhdHVzIGFsc28gd2l0aCBoaWdoZXIgQk1JIGJvdGggaW4gdGhlIGRpYWJldGljIGFuZCBub24tZGlhYmV0aWMgZ3JvdXBzLiBUaGUgc2hpZnQgaW4gcGVha3MgaW4gYm90aCBkZW5zaXR5IHBsb3RzIHN1Z2dlc3RzIGFzc29jaWF0aW9ucyBiZXR3ZWVuIGRpYWJldGVzIGFuZCBCTUkgd2hpY2ggZGlmZmVycyBhbW9uZyBkaWZmZXJlbnQgaW5jb21lIGFuZCBoZWFsdGggZ3JvdXBzLiAKCgo=